Started implemented Vars adapters and more varaible helper methods.
This commit is contained in:
parent
2537bcda95
commit
61709bc6d1
|
@ -95,7 +95,7 @@ pub fn on_copy(child: impl UiNode, can_run: impl FnMut(&mut WidgetContext) -> bo
|
|||
pub mod text_box {
|
||||
properties! {
|
||||
on_copy = {
|
||||
can_run: |ctx| IsEnabled::get(ctx.vars) && IsVisible::get(ctx.vars),
|
||||
can_run: |ctx| IsEnabled::get(ctx) && IsVisible::get(ctx),
|
||||
run: |ctx| {
|
||||
let text = ctx.widget_state[TextBoxTextState];
|
||||
ctx.services.clipboard().set_text(text);
|
||||
|
|
|
@ -22,12 +22,12 @@ fn main() {
|
|||
|
||||
fn font_size(font_size: RcVar<Length>) -> impl Widget {
|
||||
fn change_size(font_size: &RcVar<Length>, change: f32, ctx: &mut WidgetContext) {
|
||||
let mut size = match font_size.get(ctx.vars) {
|
||||
let mut size = match font_size.get(ctx) {
|
||||
Length::Exact(s) => *s,
|
||||
_ => todo!(),
|
||||
};
|
||||
size += pt_to_layout(change).get();
|
||||
font_size.set(ctx.vars, size);
|
||||
font_size.set(ctx, size);
|
||||
}
|
||||
section(
|
||||
"font_size",
|
||||
|
|
|
@ -423,17 +423,17 @@ impl UiNode for WidgetInstanceInfoNode {
|
|||
.zip(self.debug_vars.iter())
|
||||
{
|
||||
for (arg, var) in property.args.iter_mut().zip(vars.iter()) {
|
||||
arg.value = var.get(ctx.vars).clone();
|
||||
arg.value_version = var.version(ctx.vars);
|
||||
arg.value = var.get_clone(ctx);
|
||||
arg.value_version = var.version(ctx);
|
||||
arg.can_update = var.can_update();
|
||||
}
|
||||
}
|
||||
for (when, var) in info.whens.iter_mut().zip(self.when_vars.iter()) {
|
||||
when.condition = *var.get(ctx.vars);
|
||||
when.condition_version = var.version(ctx.vars);
|
||||
when.condition = var.copy(ctx);
|
||||
when.condition_version = var.version(ctx);
|
||||
}
|
||||
|
||||
info.parent_property = ParentPropertyName::get(ctx.vars);
|
||||
info.parent_property = ParentPropertyName::get(ctx);
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
|
@ -449,16 +449,16 @@ impl UiNode for WidgetInstanceInfoNode {
|
|||
.zip(self.debug_vars.iter())
|
||||
{
|
||||
for (arg, var) in property.args.iter_mut().zip(vars.iter()) {
|
||||
if let Some(update) = var.get_new(ctx.vars) {
|
||||
if let Some(update) = var.get_new(ctx) {
|
||||
arg.value = update.clone();
|
||||
arg.value_version = var.version(ctx.vars);
|
||||
arg.value_version = var.version(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (when, var) in info.whens.iter_mut().zip(self.when_vars.iter()) {
|
||||
if let Some(update) = var.get_new(ctx.vars) {
|
||||
if let Some(update) = var.get_new(ctx) {
|
||||
when.condition = *update;
|
||||
when.condition_version = var.version(ctx.vars);
|
||||
when.condition_version = var.version(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -557,8 +557,8 @@ impl UiNode for PropertyInfoNode {
|
|||
});
|
||||
|
||||
for (var, arg) in self.arg_debug_vars.iter().zip(info.args.iter_mut()) {
|
||||
arg.value = var.get(ctx.vars).clone();
|
||||
arg.value_version = var.version(ctx.vars);
|
||||
arg.value = var.get_clone(ctx);
|
||||
arg.value_version = var.version(ctx);
|
||||
arg.can_update = var.can_update();
|
||||
}
|
||||
}
|
||||
|
@ -570,9 +570,9 @@ impl UiNode for PropertyInfoNode {
|
|||
ctx_mtd!(self.update, ctx, mut info);
|
||||
|
||||
for (var, arg) in self.arg_debug_vars.iter_mut().zip(info.args.iter_mut()) {
|
||||
if let Some(new) = var.get_new(ctx.vars) {
|
||||
if let Some(new) = var.get_new(ctx) {
|
||||
arg.value = new.clone();
|
||||
arg.value_version = var.version(ctx.vars);
|
||||
arg.value_version = var.version(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1592,7 +1592,7 @@ where
|
|||
if let Some(args) = self.event.update(args) {
|
||||
self.child.event(ctx, args);
|
||||
|
||||
if IsEnabled::get(ctx.vars) && !args.stop_propagation_requested() && (self.filter)(ctx, args) {
|
||||
if IsEnabled::get(ctx) && !args.stop_propagation_requested() && (self.filter)(ctx, args) {
|
||||
(self.handler)(ctx, args);
|
||||
}
|
||||
} else {
|
||||
|
@ -1645,7 +1645,7 @@ where
|
|||
{
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = self.event.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && !args.stop_propagation_requested() && (self.filter)(ctx, args) {
|
||||
if IsEnabled::get(ctx) && !args.stop_propagation_requested() && (self.filter)(ctx, args) {
|
||||
(self.handler)(ctx, args);
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
|
@ -1706,7 +1706,7 @@ where
|
|||
if let Some(args) = self.event.update(args) {
|
||||
self.child.event(ctx, args);
|
||||
|
||||
if IsEnabled::get(ctx.vars) && !args.stop_propagation_requested() && (self.filter)(ctx, args) {
|
||||
if IsEnabled::get(ctx) && !args.stop_propagation_requested() && (self.filter)(ctx, args) {
|
||||
let mut task = ctx.async_task(|ctx| (self.handler)(ctx, args.clone()));
|
||||
if task.update(ctx).is_none() {
|
||||
self.tasks.push(task);
|
||||
|
@ -1774,7 +1774,7 @@ where
|
|||
{
|
||||
fn event<A: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &A) {
|
||||
if let Some(args) = self.event.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && !args.stop_propagation_requested() && (self.filter)(ctx, args) {
|
||||
if IsEnabled::get(ctx) && !args.stop_propagation_requested() && (self.filter)(ctx, args) {
|
||||
let mut task = ctx.async_task(|ctx| (self.handler)(ctx, args.clone()));
|
||||
if task.update(ctx).is_none() {
|
||||
self.tasks.push(task);
|
||||
|
|
|
@ -63,7 +63,7 @@ use std::{
|
|||
|
||||
use crate::{
|
||||
context::*,
|
||||
var::{response_channel, ResponseVar, VarValue, Vars},
|
||||
var::{response_channel, ResponseVar, VarValue, WithVars},
|
||||
};
|
||||
|
||||
#[doc(no_inline)]
|
||||
|
@ -100,7 +100,7 @@ pub use rayon;
|
|||
/// # struct SomeStruct { sum_response: ResponseVar<usize> }
|
||||
/// # impl SomeStruct {
|
||||
/// fn on_event(&mut self, ctx: &mut WidgetContext) {
|
||||
/// let (sender, response) = response_channel(ctx.vars);
|
||||
/// let (sender, response) = response_channel(ctx);
|
||||
/// self.sum_response = response;
|
||||
///
|
||||
/// task::spawn(async move {
|
||||
|
@ -111,7 +111,7 @@ pub use rayon;
|
|||
/// }
|
||||
///
|
||||
/// fn on_update(&mut self, ctx: &mut WidgetContext) {
|
||||
/// if let Some(result) = self.sum_response.response_new(ctx.vars) {
|
||||
/// if let Some(result) = self.sum_response.rsp_new(ctx) {
|
||||
/// println!("sum of squares 0..1000: {}", result);
|
||||
/// }
|
||||
/// }
|
||||
|
@ -181,13 +181,13 @@ where
|
|||
/// # async fn read_numbers() -> Vec<usize> { vec![] }
|
||||
/// # impl SomeStruct {
|
||||
/// fn on_event(&mut self, ctx: &mut WidgetContext) {
|
||||
/// self.sum_response = task::respond(ctx.vars, async {
|
||||
/// self.sum_response = task::respond(ctx, async {
|
||||
/// read_numbers().await.par_iter().map(|i| i * i).sum()
|
||||
/// });
|
||||
/// }
|
||||
///
|
||||
/// fn on_update(&mut self, ctx: &mut WidgetContext) {
|
||||
/// if let Some(result) = self.sum_response.response_new(ctx.vars) {
|
||||
/// if let Some(result) = self.sum_response.rsp_new(ctx) {
|
||||
/// println!("sum of squares: {}", result);
|
||||
/// }
|
||||
/// }
|
||||
|
@ -197,7 +197,7 @@ where
|
|||
/// The example `.await` for some numbers and then uses a parallel iterator to compute a result. The result is send to
|
||||
/// `sum_response` that is a [`ResponseVar`].
|
||||
#[inline]
|
||||
pub fn respond<R, F>(vars: &Vars, task: F) -> ResponseVar<R>
|
||||
pub fn respond<Vw: WithVars, R, F>(vars: &Vw, task: F) -> ResponseVar<R>
|
||||
where
|
||||
R: VarValue + Send + 'static,
|
||||
F: Future<Output = R> + Send + 'static,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//!
|
||||
//! Note: Compile error tests are in the integration tests folder: `tests/build/property`
|
||||
|
||||
use crate::context::TestWidgetContext;
|
||||
use crate::var::*;
|
||||
use crate::{property, NilUiNode, UiNode};
|
||||
|
||||
|
@ -16,10 +17,9 @@ fn basic_gen() {
|
|||
use basic_context::{code_gen, Args, ArgsImpl};
|
||||
let a = ArgsImpl::new(1);
|
||||
let b = code_gen! { named_new basic_context, __ArgsImpl { arg: 2 } };
|
||||
let a = a.unwrap().into_local();
|
||||
let b = b.unwrap().into_local();
|
||||
assert_eq!(1, *a.get_local());
|
||||
assert_eq!(2, *b.get_local());
|
||||
let test = TestWidgetContext::new();
|
||||
assert_eq!(1, a.unwrap().into_var().into_value(&test.vars));
|
||||
assert_eq!(2, b.unwrap().into_var().into_value(&test.vars));
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
|
@ -1579,7 +1579,7 @@ mod util {
|
|||
impl<C: UiNode> IsStateNode<C> {
|
||||
fn update_state(&mut self, ctx: &mut WidgetContext) {
|
||||
let wgt_state = ctx.widget_state.get::<IsStateKey>().copied().unwrap_or_default();
|
||||
if wgt_state != *self.state.get(ctx.vars) {
|
||||
if wgt_state != self.state.copy(ctx) {
|
||||
self.state.set(ctx.vars, wgt_state);
|
||||
}
|
||||
}
|
||||
|
@ -1625,12 +1625,12 @@ mod util {
|
|||
impl<C: UiNode, T: Var<&'static str>> UiNode for LiveTraceNode<C, T> {
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.init(ctx);
|
||||
ctx.widget_state.entry::<TraceKey>().or_default().insert(self.trace.get(ctx.vars));
|
||||
ctx.widget_state.entry::<TraceKey>().or_default().insert(self.trace.get(ctx));
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
if let Some(trace) = self.trace.get_new(ctx.vars) {
|
||||
if let Some(trace) = self.trace.get_new(ctx) {
|
||||
ctx.widget_state.entry::<TraceKey>().or_default().insert(trace);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ pub trait UiNode: 'static {
|
|||
/// impl<C: UiNode> UiNode for MyNode<C> {
|
||||
/// fn event<A: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &A) {
|
||||
/// if let Some(args) = ClickEvent.update(args) {
|
||||
/// if args.concerns_widget(ctx) && IsEnabled::get(ctx.vars) && !args.stop_propagation_requested() {
|
||||
/// if args.concerns_widget(ctx) && IsEnabled::get(ctx) && !args.stop_propagation_requested() {
|
||||
/// self.click_count += 1;
|
||||
/// args.stop_propagation();
|
||||
/// println!("clicks blocked {}", self.click_count);
|
||||
|
@ -606,7 +606,7 @@ where
|
|||
{
|
||||
/// Takes the widget when the var value is `true`.
|
||||
fn update_take(&mut self, ctx: &mut WidgetContext) -> bool {
|
||||
*self.get(ctx.vars)
|
||||
*self.get(ctx)
|
||||
}
|
||||
}
|
||||
/// An [`RcNodeTakeSignal`] that takes the widget when `custom` returns `true`.
|
||||
|
|
|
@ -11,9 +11,6 @@ pub use vars::*;
|
|||
mod boxed;
|
||||
pub use boxed::*;
|
||||
|
||||
mod cloning_local;
|
||||
pub use cloning_local::*;
|
||||
|
||||
mod context;
|
||||
pub use context::*;
|
||||
|
||||
|
@ -99,14 +96,6 @@ pub trait IntoVar<T: VarValue>: Clone {
|
|||
/// Converts the source value into a var.
|
||||
fn into_var(self) -> Self::Var;
|
||||
|
||||
/// Shortcut call `self.into_var().into_local()`.
|
||||
fn into_local(self) -> <<Self as IntoVar<T>>::Var as Var<T>>::AsLocal
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Var::into_local(self.into_var())
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(non_snake_case)]
|
||||
fn allowed_in_when_property_requires_IntoVar_members(&self) -> Self::Var {
|
||||
|
@ -122,38 +111,62 @@ impl<T: VarValue> IntoValue<T> for T {}
|
|||
pub trait Var<T: VarValue>: Clone + IntoVar<T> + 'static {
|
||||
/// The variable type that represents a read-only version of this type.
|
||||
type AsReadOnly: Var<T>;
|
||||
/// The variable type that represents a version of this type that provides direct access
|
||||
/// to its value without a [`VarsRead`] reference.
|
||||
type AsLocal: VarLocal<T>;
|
||||
|
||||
// TODO when GATs are stable:
|
||||
// type Map<B: VarValue, M: FnMut(&T) -> B> : Var<B>;
|
||||
// type MapBidi<B: VarValue, M: FnMut(&T) -> B, N: FnMut(&B) -> T> : Var<B>;
|
||||
|
||||
/// References the value.
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a T;
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a T;
|
||||
|
||||
/// Copy the value.
|
||||
#[inline]
|
||||
fn copy<Vr: WithVarsRead>(&self, vars: &Vr) -> T
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
vars.with(|v| *self.get(v))
|
||||
}
|
||||
|
||||
/// Clone the value.
|
||||
#[inline]
|
||||
fn get_clone<Vr: WithVarsRead>(&self, vars: &Vr) -> T {
|
||||
vars.with(|v| self.get(v).clone())
|
||||
}
|
||||
|
||||
/// References the value if [`is_new`](Self::is_new).
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a T>;
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a T>;
|
||||
|
||||
/// Copy the value if [`is_new`](Self::is_new).
|
||||
#[inline]
|
||||
fn copy_new<Vw: WithVars>(&self, vars: &Vw) -> Option<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
vars.with(|v| self.get_new(v).copied())
|
||||
}
|
||||
|
||||
/// Clone the value if [`is_new`](Self::is_new).
|
||||
#[inline]
|
||||
fn clone_new<Vw: WithVars>(&self, vars: &Vw) -> Option<T> {
|
||||
vars.with(|v| self.get_new(v).cloned())
|
||||
}
|
||||
|
||||
/// If the variable value changed in this update.
|
||||
///
|
||||
/// When the variable value changes this stays `true` for one app update cycle.
|
||||
#[inline]
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
self.get_new(vars).is_some()
|
||||
}
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool;
|
||||
|
||||
/// Gets the variable value version.
|
||||
///
|
||||
/// The version is a different number every time the value is modified, you can use this to monitor
|
||||
/// variable change outside of the window of opportunity of [`is_new`](Self::is_new).
|
||||
fn version(&self, vars: &VarsRead) -> u32;
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32;
|
||||
|
||||
/// If the variable cannot be set or modified right now.
|
||||
///
|
||||
/// **Note** this can change unless the variable is [`always_read_only`](Self::always_read_only).
|
||||
fn is_read_only(&self, vars: &Vars) -> bool;
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool;
|
||||
|
||||
/// If the variable can never be set or modified.
|
||||
///
|
||||
|
@ -165,23 +178,28 @@ pub trait Var<T: VarValue>: Clone + IntoVar<T> + 'static {
|
|||
/// **Note** this can be `true` even if the variable is [`always_read_only`](Self::always_read_only).
|
||||
fn can_update(&self) -> bool;
|
||||
|
||||
/// Convert this variable to the value, if the variable is a reference, clones the value.
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> T;
|
||||
|
||||
/// Schedule a modification of the variable value.
|
||||
///
|
||||
/// The variable is marked as *new* only if the closure input is dereferenced as `mut`.
|
||||
fn modify<M>(&self, vars: &Vars, modify: M) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, M>(&self, vars: &Vw, modify: M) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
M: FnOnce(&mut VarModify<T>) + 'static;
|
||||
|
||||
/// Causes the variable to notify update without changing the value.
|
||||
#[inline]
|
||||
fn touch(&self, vars: &Vars) -> Result<(), VarIsReadOnly> {
|
||||
fn touch<Vw: WithVars>(&self, vars: &Vw) -> Result<(), VarIsReadOnly> {
|
||||
self.modify(vars, |v| v.touch())
|
||||
}
|
||||
|
||||
/// Schedule a new value for the variable.
|
||||
#[inline]
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
{
|
||||
let new_value = new_value.into();
|
||||
|
@ -190,8 +208,9 @@ pub trait Var<T: VarValue>: Clone + IntoVar<T> + 'static {
|
|||
|
||||
/// Schedule a new value for the variable, but only if the current value is not equal to `new_value`.
|
||||
#[inline]
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
T: PartialEq,
|
||||
{
|
||||
|
@ -199,17 +218,19 @@ pub trait Var<T: VarValue>: Clone + IntoVar<T> + 'static {
|
|||
Err(VarIsReadOnly)
|
||||
} else {
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
let _r = self.set(vars, new_value);
|
||||
debug_assert!(
|
||||
_r.is_ok(),
|
||||
"variable type `{}` said it was not read-only but returned `VarIsReadOnly` on set",
|
||||
std::any::type_name::<Self>()
|
||||
);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
vars.with(|vars| {
|
||||
if self.get(vars) != &new_value {
|
||||
let _r = self.set(vars, new_value);
|
||||
debug_assert!(
|
||||
_r.is_ok(),
|
||||
"variable type `{}` said it was not read-only but returned `VarIsReadOnly` on set",
|
||||
std::any::type_name::<Self>()
|
||||
);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,9 +246,6 @@ pub trait Var<T: VarValue>: Clone + IntoVar<T> + 'static {
|
|||
/// Convert this variable to one that cannot be set or modified.
|
||||
fn into_read_only(self) -> Self::AsReadOnly;
|
||||
|
||||
/// Convert this variable to one that provides direct access to the current value.
|
||||
fn into_local(self) -> Self::AsLocal;
|
||||
|
||||
/// Create a read-only variable with a value that is mapped from this variable.
|
||||
///
|
||||
/// The value of the map variable is kept up-to-date with the value of this variable, `map` is called every
|
||||
|
@ -385,29 +403,6 @@ impl<'a, T: VarValue> DerefMut for VarModify<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A [`Var`] that provide direct access to its value without holding a [`Vars`] reference.
|
||||
///
|
||||
/// This is only possible if the value is local, so variable with shared values
|
||||
/// will keep a clone of the value locally if converted to [`VarLocal`].
|
||||
pub trait VarLocal<T: VarValue>: Var<T> {
|
||||
/// Reference the current value.
|
||||
fn get_local(&self) -> &T;
|
||||
|
||||
/// Initializes local clone of the value, if needed.
|
||||
///
|
||||
/// This must be called in the [`UiNode::init`](crate::UiNode::init) method.
|
||||
///
|
||||
/// Returns a reference to the local value for convenience.
|
||||
fn init_local<'a>(&'a mut self, vars: &'a Vars) -> &'a T;
|
||||
|
||||
/// Updates the local clone of the value, if needed.
|
||||
///
|
||||
/// This must be called in the [`UiNode::update`](crate::UiNode::update) method.
|
||||
///
|
||||
/// Returns a reference to the local value if the value is new.
|
||||
fn update_local<'a>(&'a mut self, vars: &'a Vars) -> Option<&'a T>;
|
||||
}
|
||||
|
||||
/// New [`impl Var<T>`](Var) from an expression with interpolated *vars*.
|
||||
///
|
||||
/// # Interpolation
|
||||
|
|
|
@ -6,18 +6,14 @@ use super::*;
|
|||
/// it can store any type of var.
|
||||
pub type BoxedVar<T> = Box<dyn VarBoxed<T>>;
|
||||
|
||||
/// A [`VarLocal`] in a box.
|
||||
///
|
||||
/// This type uses dynamic dispatch to access the generic methods of [`Var`], in exchange
|
||||
/// it can store any type of var.
|
||||
pub type BoxedLocalVar<T> = Box<dyn VarLocalBoxed<T>>;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait VarBoxed<T: VarValue> {
|
||||
fn get_boxed<'a>(&'a self, vars: &'a VarsRead) -> &'a T;
|
||||
fn get_new_boxed<'a>(&'a self, vars: &'a Vars) -> Option<&'a T>;
|
||||
fn is_new_boxed(&self, vars: &Vars) -> bool;
|
||||
fn version_boxed<'a>(&'a self, vars: &'a VarsRead) -> u32;
|
||||
fn is_read_only_boxed(&self, vars: &Vars) -> bool;
|
||||
fn into_value_boxed(self: Box<Self>, vars: &VarsRead) -> T;
|
||||
fn always_read_only_boxed(&self) -> bool;
|
||||
fn can_update_boxed(&self) -> bool;
|
||||
fn modify_boxed(&self, vars: &Vars, modify: Box<dyn FnOnce(&mut VarModify<T>)>) -> Result<(), VarIsReadOnly>;
|
||||
|
@ -25,38 +21,57 @@ pub trait VarBoxed<T: VarValue> {
|
|||
fn clone_boxed(&self) -> BoxedVar<T>;
|
||||
}
|
||||
impl<T: VarValue, V: Var<T>> VarBoxed<T> for V {
|
||||
#[inline]
|
||||
fn get_boxed<'a>(&'a self, vars: &'a VarsRead) -> &'a T {
|
||||
self.get(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new_boxed<'a>(&'a self, vars: &'a Vars) -> Option<&'a T> {
|
||||
self.get_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new_boxed(&self, vars: &Vars) -> bool {
|
||||
self.is_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_value_boxed(self: Box<Self>, vars: &VarsRead) -> T {
|
||||
self.into_value(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version_boxed<'a>(&'a self, vars: &'a VarsRead) -> u32 {
|
||||
self.version(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only_boxed(&self, vars: &Vars) -> bool {
|
||||
self.is_read_only(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn always_read_only_boxed(&self) -> bool {
|
||||
self.always_read_only()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn can_update_boxed(&self) -> bool {
|
||||
self.can_update()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn modify_boxed(&self, vars: &Vars, modify: Box<dyn FnOnce(&mut VarModify<T>)>) -> Result<(), VarIsReadOnly> {
|
||||
self.modify(vars, modify)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_boxed(&self, vars: &Vars, new_value: T) -> Result<(), VarIsReadOnly> {
|
||||
self.set(vars, new_value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_boxed(&self) -> BoxedVar<T> {
|
||||
self.clone().boxed()
|
||||
}
|
||||
|
@ -68,48 +83,68 @@ impl<T: VarValue> Clone for BoxedVar<T> {
|
|||
}
|
||||
impl<T: VarValue> Var<T> for BoxedVar<T> {
|
||||
type AsReadOnly = BoxedVar<T>;
|
||||
type AsLocal = CloningLocalVar<T, Self>;
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a T {
|
||||
self.as_ref().get_boxed(vars)
|
||||
#[inline]
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a T {
|
||||
self.as_ref().get_boxed(vars.as_ref())
|
||||
}
|
||||
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a T> {
|
||||
self.as_ref().get_new_boxed(vars)
|
||||
#[inline]
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a T> {
|
||||
self.as_ref().get_new_boxed(vars.as_ref())
|
||||
}
|
||||
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
self.as_ref().version_boxed(vars)
|
||||
#[inline]
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| self.as_ref().is_new_boxed(vars))
|
||||
}
|
||||
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
self.as_ref().is_read_only_boxed(vars)
|
||||
#[inline]
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> T {
|
||||
vars.with(|vars| self.into_value_boxed(vars))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|vars| self.as_ref().version_boxed(vars))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| self.as_ref().is_read_only_boxed(vars))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn always_read_only(&self) -> bool {
|
||||
self.as_ref().always_read_only_boxed()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn can_update(&self) -> bool {
|
||||
self.as_ref().can_update_boxed()
|
||||
}
|
||||
|
||||
fn modify<M>(&self, vars: &Vars, modify: M) -> Result<(), VarIsReadOnly>
|
||||
#[inline]
|
||||
fn modify<Vw, M>(&self, vars: &Vw, modify: M) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
M: FnOnce(&mut VarModify<T>) + 'static,
|
||||
{
|
||||
self.as_ref().modify_boxed(vars, Box::new(modify))
|
||||
vars.with(|vars| self.as_ref().modify_boxed(vars, Box::new(modify)))
|
||||
}
|
||||
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
#[inline]
|
||||
fn set<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
{
|
||||
self.as_ref().set_boxed(vars, new_value.into())
|
||||
vars.with(|vars| self.as_ref().set_boxed(vars, new_value.into()))
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
T: PartialEq,
|
||||
{
|
||||
|
@ -117,15 +152,18 @@ impl<T: VarValue> Var<T> for BoxedVar<T> {
|
|||
Err(VarIsReadOnly)
|
||||
} else {
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
let _ = self.set(vars, new_value);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
vars.with(|vars| {
|
||||
if self.get(vars) != &new_value {
|
||||
let _ = self.set(vars, new_value);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
if self.always_read_only() {
|
||||
self
|
||||
|
@ -133,133 +171,12 @@ impl<T: VarValue> Var<T> for BoxedVar<T> {
|
|||
ReadOnlyVar::new(self).boxed()
|
||||
}
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
impl<T: VarValue> IntoVar<T> for BoxedVar<T> {
|
||||
type Var = Self;
|
||||
|
||||
#[inline]
|
||||
fn into_var(self) -> Self::Var {
|
||||
self
|
||||
}
|
||||
}
|
||||
#[doc(hidden)]
|
||||
pub trait VarLocalBoxed<T: VarValue>: VarBoxed<T> {
|
||||
fn get_local_boxed(&self) -> &T;
|
||||
fn init_local_boxed<'a>(&'a mut self, vars: &'a Vars) -> &'a T;
|
||||
fn update_local_boxed<'a>(&'a mut self, vars: &'a Vars) -> Option<&'a T>;
|
||||
fn clone_local_boxed(&self) -> BoxedLocalVar<T>;
|
||||
}
|
||||
impl<T: VarValue, V: VarLocal<T>> VarLocalBoxed<T> for V {
|
||||
fn get_local_boxed(&self) -> &T {
|
||||
self.get_local()
|
||||
}
|
||||
|
||||
fn init_local_boxed<'a>(&'a mut self, vars: &'a Vars) -> &'a T {
|
||||
self.init_local(vars)
|
||||
}
|
||||
|
||||
fn update_local_boxed<'a>(&'a mut self, vars: &'a Vars) -> Option<&'a T> {
|
||||
self.update_local(vars)
|
||||
}
|
||||
|
||||
fn clone_local_boxed(&self) -> BoxedLocalVar<T> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: VarValue> Clone for BoxedLocalVar<T> {
|
||||
fn clone(&self) -> Self {
|
||||
self.clone_local_boxed()
|
||||
}
|
||||
}
|
||||
impl<T: VarValue> Var<T> for BoxedLocalVar<T> {
|
||||
type AsReadOnly = ReadOnlyVar<T, Self>;
|
||||
type AsLocal = Self;
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a T {
|
||||
self.as_ref().get_boxed(vars)
|
||||
}
|
||||
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a T> {
|
||||
self.as_ref().get_new_boxed(vars)
|
||||
}
|
||||
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
self.as_ref().version_boxed(vars)
|
||||
}
|
||||
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
self.as_ref().is_read_only_boxed(vars)
|
||||
}
|
||||
|
||||
fn always_read_only(&self) -> bool {
|
||||
self.as_ref().always_read_only_boxed()
|
||||
}
|
||||
|
||||
fn can_update(&self) -> bool {
|
||||
self.as_ref().can_update_boxed()
|
||||
}
|
||||
|
||||
fn modify<M>(&self, vars: &Vars, modify: M) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
M: FnOnce(&mut VarModify<T>) + 'static,
|
||||
{
|
||||
self.as_ref().modify_boxed(vars, Box::new(modify))
|
||||
}
|
||||
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
N: Into<T>,
|
||||
{
|
||||
self.as_ref().set_boxed(vars, new_value.into())
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
N: Into<T>,
|
||||
T: PartialEq,
|
||||
{
|
||||
if self.is_read_only(vars) {
|
||||
Err(VarIsReadOnly)
|
||||
} else {
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
let _ = self.set(vars, new_value);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<T: VarValue> IntoVar<T> for BoxedLocalVar<T> {
|
||||
type Var = Self;
|
||||
|
||||
fn into_var(self) -> Self::Var {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<T: VarValue> VarLocal<T> for BoxedLocalVar<T> {
|
||||
fn get_local(&self) -> &T {
|
||||
self.as_ref().get_local_boxed()
|
||||
}
|
||||
|
||||
fn init_local<'a>(&'a mut self, vars: &'a Vars) -> &'a T {
|
||||
self.as_mut().init_local_boxed(vars)
|
||||
}
|
||||
|
||||
fn update_local<'a>(&'a mut self, vars: &'a Vars) -> Option<&'a T> {
|
||||
self.as_mut().update_local_boxed(vars)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
use super::*;
|
||||
|
||||
/// A [`VarLocal`] that keeps a clone of the value locally.
|
||||
pub struct CloningLocalVar<T: VarValue, V: Var<T>> {
|
||||
source: V,
|
||||
local_version: u32,
|
||||
local: Option<T>,
|
||||
}
|
||||
impl<T: VarValue, V: Var<T>> CloningLocalVar<T, V> {
|
||||
/// New uninitialized.
|
||||
pub fn new(source: V) -> Self {
|
||||
Self {
|
||||
source,
|
||||
local_version: 0,
|
||||
local: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: VarValue, V: Var<T> + Clone> Clone for CloningLocalVar<T, V> {
|
||||
fn clone(&self) -> Self {
|
||||
CloningLocalVar {
|
||||
source: self.source.clone(),
|
||||
local_version: self.local_version,
|
||||
local: self.local.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T: VarValue, V: Var<T>> Var<T> for CloningLocalVar<T, V> {
|
||||
type AsReadOnly = V::AsReadOnly;
|
||||
|
||||
type AsLocal = Self;
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a T {
|
||||
self.source.get(vars)
|
||||
}
|
||||
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a T> {
|
||||
self.source.get_new(vars)
|
||||
}
|
||||
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
self.source.version(vars)
|
||||
}
|
||||
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
self.source.is_read_only(vars)
|
||||
}
|
||||
|
||||
fn always_read_only(&self) -> bool {
|
||||
self.source.always_read_only()
|
||||
}
|
||||
|
||||
fn can_update(&self) -> bool {
|
||||
self.source.can_update()
|
||||
}
|
||||
|
||||
fn modify<M>(&self, vars: &Vars, modify: M) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
M: FnOnce(&mut VarModify<T>) + 'static,
|
||||
{
|
||||
self.source.modify(vars, modify)
|
||||
}
|
||||
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
N: Into<T>,
|
||||
{
|
||||
self.source.set(vars, new_value)
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
N: Into<T>,
|
||||
T: PartialEq,
|
||||
{
|
||||
self.source.set_ne(vars, new_value)
|
||||
}
|
||||
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
self.source.into_read_only()
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<T: VarValue, V: Var<T>> IntoVar<T> for CloningLocalVar<T, V> {
|
||||
type Var = Self;
|
||||
|
||||
fn into_var(self) -> Self::Var {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<T: VarValue, V: Var<T>> VarLocal<T> for CloningLocalVar<T, V> {
|
||||
fn get_local(&self) -> &T {
|
||||
self.local.as_ref().expect("local var not initialized")
|
||||
}
|
||||
|
||||
fn init_local<'a>(&'a mut self, vars: &'a Vars) -> &'a T {
|
||||
let version = self.source.version(vars);
|
||||
let value = self.source.get(vars);
|
||||
if self.local_version != version || self.local.is_none() {
|
||||
self.local = Some(value.clone());
|
||||
self.local_version = version;
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
fn update_local<'a>(&'a mut self, vars: &'a Vars) -> Option<&'a T> {
|
||||
if let Some(new_value) = self.source.get_new(vars) {
|
||||
let version = self.source.version(vars);
|
||||
if version != self.local_version {
|
||||
self.local = Some(new_value.clone());
|
||||
self.local_version = version;
|
||||
}
|
||||
Some(new_value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,14 +33,14 @@ impl<C: ContextVar> Default for ContextVarProxy<C> {
|
|||
impl<C: ContextVar> Var<C::Type> for ContextVarProxy<C> {
|
||||
type AsReadOnly = Self;
|
||||
|
||||
type AsLocal = CloningLocalVar<C::Type, Self>;
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a C::Type {
|
||||
vars.context_var::<C>().0
|
||||
#[inline]
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a C::Type {
|
||||
vars.as_ref().context_var::<C>().0
|
||||
}
|
||||
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a C::Type> {
|
||||
let info = vars.context_var::<C>();
|
||||
#[inline]
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a C::Type> {
|
||||
let info = vars.as_ref().context_var::<C>();
|
||||
if info.1 {
|
||||
Some(info.0)
|
||||
} else {
|
||||
|
@ -48,60 +48,74 @@ impl<C: ContextVar> Var<C::Type> for ContextVarProxy<C> {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
vars.context_var::<C>().1
|
||||
#[inline]
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|v| v.context_var::<C>().1)
|
||||
}
|
||||
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
vars.context_var::<C>().2
|
||||
#[inline]
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> C::Type {
|
||||
self.get_clone(vars)
|
||||
}
|
||||
|
||||
fn is_read_only(&self, _: &Vars) -> bool {
|
||||
#[inline]
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|v| v.context_var::<C>().2)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only<Vr: WithVars>(&self, _: &Vr) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn always_read_only(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn can_update(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn modify<M>(&self, _: &Vars, _: M) -> Result<(), VarIsReadOnly>
|
||||
#[inline]
|
||||
fn modify<Vw, M>(&self, _: &Vw, _: M) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
M: FnOnce(&mut VarModify<C::Type>) + 'static,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
fn set<N>(&self, _: &Vars, _: N) -> Result<(), VarIsReadOnly>
|
||||
#[inline]
|
||||
fn set<Vw, N>(&self, _: &Vw, _: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<C::Type>,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, _: &Vars, _: N) -> Result<bool, VarIsReadOnly>
|
||||
#[inline]
|
||||
fn set_ne<Vw, N>(&self, _: &Vw, _: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<C::Type>,
|
||||
C::Type: PartialEq,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContextVar> IntoVar<C::Type> for ContextVarProxy<C> {
|
||||
type Var = Self;
|
||||
|
||||
#[inline]
|
||||
fn into_var(self) -> Self::Var {
|
||||
self
|
||||
}
|
||||
|
@ -211,28 +225,30 @@ macro_rules! __context_var_inner {
|
|||
/// References the value in the current `vars` context.
|
||||
#[inline]
|
||||
#[allow(unused)]
|
||||
pub fn get<'a>(vars: &'a $crate::var::VarsRead) -> &'a $type {
|
||||
pub fn get<'a, Vr: AsRef<$crate::var::VarsRead>>(vars: &'a Vr) -> &'a $type {
|
||||
$crate::var::Var::get($crate::var::ContextVarProxy::<Self>::static_ref(), vars)
|
||||
}
|
||||
|
||||
// TODO copy, clone
|
||||
|
||||
/// References the value in the current `vars` context if it is marked as new.
|
||||
#[inline]
|
||||
#[allow(unused)]
|
||||
pub fn get_new<'a>(vars: &'a $crate::var::Vars) -> Option<&'a $type> {
|
||||
pub fn get_new<'a, Vw: AsRef<$crate::var::Vars>>(vars: &'a Vw) -> Option<&'a $type> {
|
||||
$crate::var::Var::get_new($crate::var::ContextVarProxy::<Self>::static_ref(), vars)
|
||||
}
|
||||
|
||||
/// If the value in the current `vars` context is marked as new.
|
||||
#[inline]
|
||||
#[allow(unused)]
|
||||
pub fn is_new(vars: & $crate::var::Vars) -> bool {
|
||||
pub fn is_new<Vw: $crate::var::WithVars>(vars: &Vw) -> bool {
|
||||
$crate::var::Var::is_new($crate::var::ContextVarProxy::<Self>::static_ref(), vars)
|
||||
}
|
||||
|
||||
/// Gets the version of the value in the current `vars` context.
|
||||
#[inline]
|
||||
#[allow(unused)]
|
||||
pub fn version(vars: & $crate::var::VarsRead) -> u32 {
|
||||
pub fn version<Vr: $crate::var::WithVarsRead>(vars: &Vr) -> u32 {
|
||||
$crate::var::Var::version($crate::var::ContextVarProxy::<Self>::static_ref(), vars)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,9 @@ where
|
|||
}
|
||||
|
||||
/// Get the value, applies the mapping if the value is out of sync.
|
||||
pub fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
pub fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
// SAFETY: access to value is safe because `source` needs a `&mut Vars` to change its version
|
||||
// and we change the value only in the first call to `get` with the new source version.
|
||||
|
||||
|
@ -110,7 +112,9 @@ where
|
|||
}
|
||||
|
||||
/// Gets the value if [`is_new`](Self::is_new).
|
||||
pub fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
pub fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
if self.0.source.is_new(vars) {
|
||||
let value = self.get(vars);
|
||||
if self.0.last_update_id.get() == vars.update_id() {
|
||||
|
@ -127,15 +131,17 @@ where
|
|||
///
|
||||
/// Returns `true` if the source var is new and the new value was approved by the filter.
|
||||
#[inline]
|
||||
pub fn is_new(&self, vars: &Vars) -> bool {
|
||||
self.get_new(vars).is_some()
|
||||
pub fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| self.get_new(vars).is_some())
|
||||
}
|
||||
|
||||
/// Gets the up-to-date value version.
|
||||
#[inline]
|
||||
pub fn version(&self, vars: &VarsRead) -> u32 {
|
||||
let _ = self.get(vars);
|
||||
self.0.source.version(vars)
|
||||
pub fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|vars| {
|
||||
let _ = self.get(vars);
|
||||
self.0.source.version(vars)
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets the number of [`RcFilterMapVar`] that point to this same variable.
|
||||
|
@ -172,30 +178,32 @@ where
|
|||
{
|
||||
type AsReadOnly = Self;
|
||||
|
||||
type AsLocal = CloningLocalVar<B, Self>;
|
||||
|
||||
#[inline]
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
self.get(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
self.get_new(vars)
|
||||
}
|
||||
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> B {
|
||||
self.get_clone(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.version(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only(&self, _: &Vars) -> bool {
|
||||
fn is_read_only<Vr: WithVars>(&self, _: &Vr) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -210,24 +218,27 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn modify<Mo>(&self, _: &Vars, _: Mo) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, Mo>(&self, _: &Vw, _: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<N>(&self, _: &Vars, _: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, _: &Vw, _: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<B>,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_ne<N>(&self, _: &Vars, _: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, _: &Vw, _: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
|
@ -238,11 +249,6 @@ where
|
|||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
impl<A, B, I, M, S> IntoVar<B> for RcFilterMapVar<A, B, I, M, S>
|
||||
where
|
||||
|
@ -311,7 +317,8 @@ where
|
|||
}
|
||||
|
||||
/// Get the value, applies the mapping if the value is out of sync.
|
||||
pub fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
pub fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
let vars = vars.as_ref();
|
||||
// SAFETY: access to value is safe because `source` needs a `&mut Vars` to change its version
|
||||
// and we change the value only in the first call to `get` with the new source version.
|
||||
|
||||
|
@ -345,7 +352,9 @@ where
|
|||
}
|
||||
|
||||
/// Gets the value if [`is_new`](Self::is_new).
|
||||
pub fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
pub fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
if self.0.source.is_new(vars) {
|
||||
let value = self.get(vars);
|
||||
if self.0.last_update_id.get() == vars.update_id() {
|
||||
|
@ -362,20 +371,22 @@ where
|
|||
///
|
||||
/// Returns `true` if the source var is new and the new value was approved by the filter.
|
||||
#[inline]
|
||||
pub fn is_new(&self, vars: &Vars) -> bool {
|
||||
self.get_new(vars).is_some()
|
||||
pub fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| self.get_new(vars).is_some())
|
||||
}
|
||||
|
||||
/// Gets the up-to-date value version.
|
||||
#[inline]
|
||||
pub fn version(&self, vars: &VarsRead) -> u32 {
|
||||
let _ = self.get(vars);
|
||||
self.0.source.version(vars)
|
||||
pub fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|vars| {
|
||||
let _ = self.get(vars);
|
||||
self.0.source.version(vars)
|
||||
})
|
||||
}
|
||||
|
||||
/// If the source variable is currently read-only. You can only map-back when the source is read-write.
|
||||
#[inline]
|
||||
pub fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
pub fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.0.source.is_read_only(vars)
|
||||
}
|
||||
|
||||
|
@ -393,8 +404,9 @@ where
|
|||
}
|
||||
|
||||
/// Schedules a `map -> modify -> map_back -> set` chain.
|
||||
fn modify<Mo>(&self, vars: &Vars, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, Mo>(&self, vars: &Vw, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
let self_ = self.clone();
|
||||
|
@ -415,8 +427,9 @@ where
|
|||
///
|
||||
/// Returns `Err(VarIsReadOnly)` if the source variable is currently read-only. Returns `Ok(bool)` where the `bool`
|
||||
/// indicates if the map-back function produced some value.
|
||||
fn set<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
fn set<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
{
|
||||
if self.0.source.is_read_only(vars) {
|
||||
|
@ -433,8 +446,9 @@ where
|
|||
///
|
||||
/// Returns `Err(VarIsReadOnly)` if the source variable is currently read-only. Returns `Ok(bool)` where the `bool`
|
||||
/// indicates if the source variable will update.
|
||||
fn set_ne<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
|
@ -442,16 +456,18 @@ where
|
|||
Err(VarIsReadOnly)
|
||||
} else {
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
if let Some(new_value) = self.0.map_back.borrow_mut()(new_value) {
|
||||
let _ = self.0.source.set(vars, new_value);
|
||||
Ok(true)
|
||||
vars.with(|vars| {
|
||||
if self.get(vars) != &new_value {
|
||||
if let Some(new_value) = self.0.map_back.borrow_mut()(new_value) {
|
||||
let _ = self.0.source.set(vars, new_value);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,30 +524,33 @@ where
|
|||
{
|
||||
type AsReadOnly = ReadOnlyVar<B, Self>;
|
||||
|
||||
type AsLocal = CloningLocalVar<B, Self>;
|
||||
|
||||
#[inline]
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
self.get(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
self.get_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> B {
|
||||
self.get_clone(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.version(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_read_only(vars)
|
||||
}
|
||||
|
||||
|
@ -546,24 +565,27 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn modify<Mo>(&self, vars: &Vars, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, Mo>(&self, vars: &Vw, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
self.modify(vars, modify)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
{
|
||||
self.set(vars, new_value).map(|_| ())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_ne<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
|
@ -574,11 +596,6 @@ where
|
|||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
impl<A, B, I, M, N, S> IntoVar<B> for RcFilterMapBidiVar<A, B, I, M, N, S>
|
||||
where
|
||||
|
|
|
@ -46,7 +46,9 @@ where
|
|||
}
|
||||
|
||||
/// Get the value, applies the mapping if the value is out of sync.
|
||||
pub fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
pub fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
// SAFETY: access to value is safe because `source` needs a `&mut Vars` to change its version
|
||||
// and we change the value only in the first call to `get` with the new source version.
|
||||
|
||||
|
@ -67,7 +69,9 @@ where
|
|||
}
|
||||
|
||||
/// Get the value if the source var updated in the last update.
|
||||
pub fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
pub fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
if self.0.source.is_new(vars) {
|
||||
Some(self.get(vars))
|
||||
} else {
|
||||
|
@ -77,13 +81,13 @@ where
|
|||
|
||||
/// Gets if the source var updated in the last update.
|
||||
#[inline]
|
||||
pub fn is_new(&self, vars: &Vars) -> bool {
|
||||
pub fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.0.source.is_new(vars)
|
||||
}
|
||||
|
||||
/// Gets the source var value version.
|
||||
#[inline]
|
||||
pub fn version(&self, vars: &VarsRead) -> u32 {
|
||||
pub fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.0.source.version(vars)
|
||||
}
|
||||
|
||||
|
@ -121,30 +125,33 @@ where
|
|||
{
|
||||
type AsReadOnly = Self;
|
||||
|
||||
type AsLocal = CloningLocalVar<B, Self>;
|
||||
|
||||
#[inline]
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
self.get(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
self.get_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> B {
|
||||
self.get_clone(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.version(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only(&self, _: &Vars) -> bool {
|
||||
fn is_read_only<Vw: WithVars>(&self, _: &Vw) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -159,24 +166,27 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn modify<Mo>(&self, _: &Vars, _: Mo) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, Mo>(&self, _: &Vw, _: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<N>(&self, _: &Vars, _: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, _: &Vw, _: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<B>,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_ne<N>(&self, _: &Vars, _: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, _: &Vw, _: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
|
@ -187,11 +197,6 @@ where
|
|||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
impl<A, B, M, S> IntoVar<B> for RcMapVar<A, B, M, S>
|
||||
where
|
||||
|
@ -252,7 +257,9 @@ where
|
|||
}
|
||||
|
||||
/// Get the value, applies the mapping if the value is out of sync.
|
||||
pub fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
pub fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
// SAFETY: access to value is safe because `source` needs a `&mut Vars` to change its version
|
||||
// and we change the value only in the first call to `get` with the new source version.
|
||||
|
||||
|
@ -273,7 +280,9 @@ where
|
|||
}
|
||||
|
||||
/// Get the value if the source var updated in the last update.
|
||||
pub fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
pub fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
if self.0.source.is_new(vars) {
|
||||
Some(self.get(vars))
|
||||
} else {
|
||||
|
@ -283,19 +292,19 @@ where
|
|||
|
||||
/// Gets if the source var updated in the last update.
|
||||
#[inline]
|
||||
pub fn is_new(&self, vars: &Vars) -> bool {
|
||||
pub fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.0.source.is_new(vars)
|
||||
}
|
||||
|
||||
/// Gets the source var value version.
|
||||
#[inline]
|
||||
pub fn version(&self, vars: &VarsRead) -> u32 {
|
||||
pub fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.0.source.version(vars)
|
||||
}
|
||||
|
||||
/// If the source variable is currently read-only. You can only map-back when the source is read-write.
|
||||
#[inline]
|
||||
pub fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
pub fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.0.source.is_read_only(vars)
|
||||
}
|
||||
|
||||
|
@ -313,8 +322,9 @@ where
|
|||
}
|
||||
|
||||
/// Schedules a `map -> modify -> map_back -> set` chain.
|
||||
fn modify<Mo>(&self, vars: &Vars, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, Mo>(&self, vars: &Vw, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
let self_ = self.clone();
|
||||
|
@ -329,8 +339,9 @@ where
|
|||
}
|
||||
|
||||
/// Map back the value and schedules a `set` in the source variable.
|
||||
fn set<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
{
|
||||
if self.0.source.is_read_only(vars) {
|
||||
|
@ -342,8 +353,9 @@ where
|
|||
}
|
||||
|
||||
/// If `new_value` is not equal to the current value maps-back and schedules an assign in the source value.
|
||||
fn set_ne<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
|
@ -351,12 +363,14 @@ where
|
|||
Err(VarIsReadOnly)
|
||||
} else {
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
let _ = self.0.source.set(vars, self.0.map_back.borrow_mut()(new_value));
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
vars.with(|vars| {
|
||||
if self.get(vars) != &new_value {
|
||||
let _ = self.0.source.set(vars, self.0.map_back.borrow_mut()(new_value));
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -411,30 +425,33 @@ where
|
|||
{
|
||||
type AsReadOnly = ReadOnlyVar<B, Self>;
|
||||
|
||||
type AsLocal = CloningLocalVar<B, Self>;
|
||||
|
||||
#[inline]
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
self.get(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
self.get_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> B {
|
||||
self.get_clone(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.version(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_read_only(vars)
|
||||
}
|
||||
|
||||
|
@ -449,24 +466,27 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn modify<Mo>(&self, vars: &Vars, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, Mo>(&self, vars: &Vw, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
self.modify(vars, modify)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
{
|
||||
self.set(vars, new_value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_ne<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
|
@ -477,11 +497,6 @@ where
|
|||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
impl<A, B, M, N, S> IntoVar<B> for RcMapBidiVar<A, B, M, N, S>
|
||||
where
|
||||
|
|
|
@ -36,25 +36,25 @@ where
|
|||
|
||||
/// Gets the mapped reference.
|
||||
#[inline]
|
||||
pub fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
pub fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
(self.map)(self.source.get(vars))
|
||||
}
|
||||
|
||||
/// Gets the mapped reference if the value of the source variable is new.
|
||||
#[inline]
|
||||
pub fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
pub fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
self.source.get_new(vars).map(|v| (self.map)(v))
|
||||
}
|
||||
|
||||
/// Gets if the value of the source variable is new.
|
||||
#[inline]
|
||||
pub fn is_new(&self, vars: &Vars) -> bool {
|
||||
pub fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.source.is_new(vars)
|
||||
}
|
||||
|
||||
/// Gets the version of the source variable value.
|
||||
#[inline]
|
||||
pub fn version(&self, vars: &VarsRead) -> u32 {
|
||||
pub fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.source.version(vars)
|
||||
}
|
||||
|
||||
|
@ -90,30 +90,32 @@ where
|
|||
{
|
||||
type AsReadOnly = Self;
|
||||
|
||||
type AsLocal = CloningLocalVar<B, Self>;
|
||||
|
||||
#[inline]
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
self.get(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
self.get_new(vars)
|
||||
}
|
||||
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> B {
|
||||
self.get_clone(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.version(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only(&self, _: &Vars) -> bool {
|
||||
fn is_read_only<Vw: WithVars>(&self, _: &Vw) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -128,24 +130,27 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn modify<Mo>(&self, _: &Vars, _: Mo) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, Mo>(&self, _: &Vw, _: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<N>(&self, _: &Vars, _: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, _: &Vw, _: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<B>,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_ne<N>(&self, _: &Vars, _: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, _: &Vw, _: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
|
@ -156,11 +161,6 @@ where
|
|||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, M, S> IntoVar<B> for MapRefVar<A, B, M, S>
|
||||
|
@ -216,25 +216,25 @@ where
|
|||
|
||||
/// Gets the mapped reference.
|
||||
#[inline]
|
||||
pub fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
pub fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
(self.map)(self.source.get(vars))
|
||||
}
|
||||
|
||||
/// Gets the mapped reference if the value of the source variable is new.
|
||||
#[inline]
|
||||
pub fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
pub fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
self.source.get_new(vars).map(|v| (self.map)(v))
|
||||
}
|
||||
|
||||
/// Gets if the value of the source variable is new.
|
||||
#[inline]
|
||||
pub fn is_new(&self, vars: &Vars) -> bool {
|
||||
pub fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.source.is_new(vars)
|
||||
}
|
||||
|
||||
/// Gets the version of the source variable value.
|
||||
#[inline]
|
||||
pub fn version(&self, vars: &VarsRead) -> u32 {
|
||||
pub fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.source.version(vars)
|
||||
}
|
||||
|
||||
|
@ -246,7 +246,7 @@ where
|
|||
|
||||
/// Gets if the source is currently read-only.
|
||||
#[inline]
|
||||
pub fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
pub fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.source.is_read_only(vars)
|
||||
}
|
||||
|
||||
|
@ -258,8 +258,9 @@ where
|
|||
}
|
||||
|
||||
/// Schedules a modification using the mapped mutable reference.
|
||||
pub fn modify<Mo>(&self, vars: &Vars, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
pub fn modify<Vw, Mo>(&self, vars: &Vw, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
let map = self.map_mut.clone();
|
||||
|
@ -269,8 +270,9 @@ where
|
|||
}
|
||||
|
||||
/// Schedules an assign to the mapped mutable reference.
|
||||
pub fn set<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
pub fn set<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
{
|
||||
let map = self.map_mut.clone();
|
||||
|
@ -281,21 +283,24 @@ where
|
|||
}
|
||||
|
||||
/// Schedules an assign to the mapped mutable reference, but only if the value is not equal.
|
||||
pub fn set_ne<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
pub fn set_ne<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
if self.is_read_only(vars) {
|
||||
Err(VarIsReadOnly)
|
||||
} else {
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
let _ = self.set(vars, new_value);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
vars.with(|vars| {
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
let _ = self.set(vars, new_value);
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -338,30 +343,33 @@ where
|
|||
{
|
||||
type AsReadOnly = ReadOnlyVar<B, Self>;
|
||||
|
||||
type AsLocal = CloningLocalVar<B, Self>;
|
||||
|
||||
#[inline]
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a B {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a B {
|
||||
self.get(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a B> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a B> {
|
||||
self.get_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> B {
|
||||
self.get_clone(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.version(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_read_only(vars)
|
||||
}
|
||||
|
||||
|
@ -376,24 +384,27 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn modify<Mo>(&self, vars: &Vars, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, Mo>(&self, vars: &Vw, modify: Mo) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Mo: FnOnce(&mut VarModify<B>) + 'static,
|
||||
{
|
||||
self.modify(vars, modify)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
{
|
||||
self.set(vars, new_value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_ne<Nv>(&self, vars: &Vars, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, Nv>(&self, vars: &Vw, new_value: Nv) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
Nv: Into<B>,
|
||||
B: PartialEq,
|
||||
{
|
||||
|
@ -404,11 +415,6 @@ where
|
|||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, M, N, S> IntoVar<B> for MapBidiRefVar<A, B, M, N, S>
|
||||
|
|
|
@ -391,26 +391,6 @@ macro_rules! impl_rc_merge_var {
|
|||
}))
|
||||
}
|
||||
|
||||
pub fn get<'a>(&'a self, vars: &'a Vars) -> &'a O {
|
||||
<Self as Var<O>>::get(self, vars)
|
||||
}
|
||||
|
||||
pub fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a O> {
|
||||
<Self as Var<O>>::get_new(self, vars)
|
||||
}
|
||||
|
||||
pub fn is_new(&self, vars: &Vars) -> bool {
|
||||
<Self as Var<O>>::is_new(self, vars)
|
||||
}
|
||||
|
||||
pub fn version(&self, vars: &Vars) -> u32 {
|
||||
<Self as Var<O>>::version(self, vars)
|
||||
}
|
||||
|
||||
pub fn can_update(&self) -> bool {
|
||||
<Self as Var<O>>::can_update(self)
|
||||
}
|
||||
|
||||
fn update_output(&self, vars: &VarsRead) {
|
||||
// SAFETY: This is safe because it only happens before the first borrow
|
||||
// of this update, and borrows cannot exist across updates because source
|
||||
|
@ -449,17 +429,17 @@ macro_rules! impl_rc_merge_var {
|
|||
Var<O> for $RcMergeVar<$($I,)+ O, $($V,)+ F> {
|
||||
type AsReadOnly = ReadOnlyVar<O, Self>;
|
||||
|
||||
type AsLocal = CloningLocalVar<O, Self>;
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a O {
|
||||
self.update_output(vars);
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a O {
|
||||
self.update_output(vars.as_ref());
|
||||
|
||||
// SAFETY:
|
||||
// This is safe because we require &mut Vars for updating.
|
||||
unsafe { &*self.0.output.get() }.as_ref().unwrap()
|
||||
}
|
||||
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a O> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a O> {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
if self.is_new(vars) {
|
||||
Some(self.get(vars))
|
||||
} else {
|
||||
|
@ -467,19 +447,35 @@ macro_rules! impl_rc_merge_var {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
#[inline]
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> O {
|
||||
vars.with(|vars| {
|
||||
self.update_output(vars);
|
||||
|
||||
match Rc::try_unwrap(self.0) {
|
||||
Ok(r) => r.output.into_inner().unwrap(),
|
||||
Err(e) => $RcMergeVar(e).get_clone(vars)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
$(self.0.vars.$n.is_new(vars))||+
|
||||
}
|
||||
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
self.update_output(vars);
|
||||
self.0.output_version.get()
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|vars| {
|
||||
self.update_output(vars);
|
||||
self.0.output_version.get()
|
||||
})
|
||||
}
|
||||
|
||||
fn is_read_only(&self, _: &Vars) -> bool {
|
||||
#[inline]
|
||||
fn is_read_only<Vw: WithVars>(&self, _: &Vw) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn always_read_only(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
@ -488,22 +484,22 @@ macro_rules! impl_rc_merge_var {
|
|||
$(self.0.vars.$n.can_update())||+
|
||||
}
|
||||
|
||||
fn set<N>(&self, _: &Vars, _: N) -> Result<(), VarIsReadOnly> where N: Into<O> {
|
||||
#[inline]
|
||||
fn set<Vw: WithVars, N>(&self, _: &Vw, _: N) -> Result<(), VarIsReadOnly> where N: Into<O> {
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, _: &Vars, _: N) -> Result<bool, VarIsReadOnly> where N: Into<O>, O: PartialEq {
|
||||
#[inline]
|
||||
fn set_ne<Vw: WithVars, N>(&self, _: &Vw, _: N) -> Result<bool, VarIsReadOnly> where N: Into<O>, O: PartialEq {
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
fn modify<F2: FnOnce(&mut VarModify<O>) + 'static>(&self, _: &Vars, _: F2) -> Result<(), VarIsReadOnly> {
|
||||
#[inline]
|
||||
fn modify<Vw: WithVars, F2: FnOnce(&mut VarModify<O>) + 'static>(&self, _: &Vw, _: F2) -> Result<(), VarIsReadOnly> {
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
|
|
@ -6,25 +6,33 @@ pub struct OwnedVar<T: VarValue>(pub T);
|
|||
impl<T: VarValue> Var<T> for OwnedVar<T> {
|
||||
type AsReadOnly = Self;
|
||||
|
||||
type AsLocal = Self;
|
||||
|
||||
#[inline]
|
||||
fn get<'a>(&'a self, _: &'a VarsRead) -> &'a T {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, _: &'a Vr) -> &'a T {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a>(&'a self, _: &'a Vars) -> Option<&'a T> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, _: &'a Vw) -> Option<&'a T> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version(&self, _: &VarsRead) -> u32 {
|
||||
fn is_new<Vw: WithVars>(&self, _: &Vw) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_value<Vr: WithVarsRead>(self, _: &Vr) -> T {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version<Vr: WithVarsRead>(&self, _: &Vr) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only(&self, _: &Vars) -> bool {
|
||||
fn is_read_only<Vw: WithVars>(&self, _: &Vw) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -39,24 +47,27 @@ impl<T: VarValue> Var<T> for OwnedVar<T> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn modify<M>(&self, _: &Vars, _: M) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, M>(&self, _: &Vw, _: M) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
M: FnOnce(&mut VarModify<T>) + 'static,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<N>(&self, _: &Vars, _: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, _: &Vw, _: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_ne<N>(&self, _: &Vars, _: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, _: &Vw, _: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
T: PartialEq,
|
||||
{
|
||||
|
@ -67,11 +78,6 @@ impl<T: VarValue> Var<T> for OwnedVar<T> {
|
|||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<T: VarValue> IntoVar<T> for OwnedVar<T> {
|
||||
type Var = Self;
|
||||
|
@ -81,23 +87,6 @@ impl<T: VarValue> IntoVar<T> for OwnedVar<T> {
|
|||
self
|
||||
}
|
||||
}
|
||||
impl<T: VarValue> VarLocal<T> for OwnedVar<T> {
|
||||
#[inline]
|
||||
fn get_local(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn init_local<'a>(&'a mut self, _: &'a Vars) -> &'a T {
|
||||
&self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update_local<'a>(&'a mut self, _: &'a Vars) -> Option<&'a T> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: VarValue> IntoVar<T> for T {
|
||||
type Var = OwnedVar<T>;
|
||||
|
||||
|
|
|
@ -26,17 +26,27 @@ impl<T: VarValue> RcVar<T> {
|
|||
|
||||
/// Reference the current value.
|
||||
#[inline]
|
||||
pub fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a T {
|
||||
let _ = vars;
|
||||
pub fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a T {
|
||||
let _vars = vars.as_ref();
|
||||
// SAFETY: this is safe because we are tying the `Vars` lifetime to the value
|
||||
// and we require `&mut Vars` to modify the value.
|
||||
unsafe { &*self.0.value.get() }
|
||||
}
|
||||
|
||||
fn copy<Vr: WithVarsRead>(&self, vars: &Vr) -> T
|
||||
where
|
||||
T: Copy, {
|
||||
|
||||
}
|
||||
|
||||
fn get_clone<Vr: WithVarsRead>(&self, vars: &Vr) -> T {
|
||||
|
||||
}
|
||||
|
||||
/// Reference the current value if it [is new](Self::is_new).
|
||||
#[inline]
|
||||
pub fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a T> {
|
||||
let _ = vars;
|
||||
pub fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a T> {
|
||||
let vars = vars.as_ref();
|
||||
if self.0.last_update_id.get() == vars.update_id() {
|
||||
Some(self.get(vars))
|
||||
} else {
|
||||
|
@ -44,48 +54,61 @@ impl<T: VarValue> RcVar<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn copy_new<Vw: WithVars>(&self, vars: &Vw) -> Option<T>
|
||||
where
|
||||
T: Copy, {
|
||||
|
||||
}
|
||||
|
||||
pub fn clone_new<Vw: WithVars>(&self, vars: &Vw) -> Option<T> {
|
||||
|
||||
}
|
||||
|
||||
/// If the current value changed in the last update.
|
||||
#[inline]
|
||||
pub fn is_new(&self, vars: &Vars) -> bool {
|
||||
self.0.last_update_id.get() == vars.update_id()
|
||||
pub fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| self.0.last_update_id.get() == vars.update_id())
|
||||
}
|
||||
|
||||
/// Gets the current value version.
|
||||
#[inline]
|
||||
pub fn version(&self, vars: &VarsRead) -> u32 {
|
||||
let _ = vars;
|
||||
self.0.version.get()
|
||||
pub fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|_| self.0.version.get())
|
||||
}
|
||||
|
||||
/// Schedule a value modification for this variable.
|
||||
#[inline]
|
||||
pub fn modify<M>(&self, vars: &Vars, modify: M)
|
||||
pub fn modify<Vw, M>(&self, vars: &Vw, modify: M)
|
||||
where
|
||||
Vw: WithVars,
|
||||
M: FnOnce(&mut VarModify<T>) + 'static,
|
||||
{
|
||||
let self_ = self.clone();
|
||||
vars.push_change(Box::new(move |update_id| {
|
||||
// SAFETY: this is safe because Vars requires a mutable reference to apply changes.
|
||||
let mut guard = VarModify::new(unsafe { &mut *self_.0.value.get() });
|
||||
modify(&mut guard);
|
||||
if guard.touched() {
|
||||
self_.0.last_update_id.set(update_id);
|
||||
self_.0.version.set(self_.0.version.get().wrapping_add(1));
|
||||
}
|
||||
guard.touched()
|
||||
}));
|
||||
vars.with(|vars| {
|
||||
let self_ = self.clone();
|
||||
vars.push_change(Box::new(move |update_id| {
|
||||
// SAFETY: this is safe because Vars requires a mutable reference to apply changes.
|
||||
let mut guard = VarModify::new(unsafe { &mut *self_.0.value.get() });
|
||||
modify(&mut guard);
|
||||
if guard.touched() {
|
||||
self_.0.last_update_id.set(update_id);
|
||||
self_.0.version.set(self_.0.version.get().wrapping_add(1));
|
||||
}
|
||||
guard.touched()
|
||||
}));
|
||||
})
|
||||
}
|
||||
|
||||
/// Causes the variable to notify update without changing the value.
|
||||
#[inline]
|
||||
pub fn touch(&self, vars: &Vars) {
|
||||
pub fn touch<Vw: WithVars>(&self, vars: &Vw) {
|
||||
self.modify(vars, |v| v.touch());
|
||||
}
|
||||
|
||||
/// Schedule a new value for this variable.
|
||||
#[inline]
|
||||
pub fn set<N>(&self, vars: &Vars, new_value: N)
|
||||
pub fn set<Vw, N>(&self, vars: &Vw, new_value: N)
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
{
|
||||
let new_value = new_value.into();
|
||||
|
@ -95,18 +118,21 @@ impl<T: VarValue> RcVar<T> {
|
|||
/// Schedule a new value for this variable, the variable will only be set if
|
||||
/// the value is not equal to `new_value`.
|
||||
#[inline]
|
||||
pub fn set_ne<N>(&self, vars: &Vars, new_value: N) -> bool
|
||||
pub fn set_ne<Vw, N>(&self, vars: &Vw, new_value: N) -> bool
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
T: PartialEq,
|
||||
{
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
self.set(vars, new_value);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
vars.with(|vars| {
|
||||
let new_value = new_value.into();
|
||||
if self.get(vars) != &new_value {
|
||||
self.set(vars, new_value);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets the number of [`RcVar`] that point to this same variable.
|
||||
|
@ -170,71 +196,108 @@ impl<T: VarValue> WeakVar<T> {
|
|||
impl<T: VarValue> Var<T> for RcVar<T> {
|
||||
type AsReadOnly = ReadOnlyVar<T, Self>;
|
||||
|
||||
type AsLocal = CloningLocalVar<T, Self>;
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a T {
|
||||
#[inline]
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a T {
|
||||
self.get(vars)
|
||||
}
|
||||
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a T> {
|
||||
fn copy<Vr: WithVarsRead>(&self, vars: &Vr) -> T
|
||||
where
|
||||
T: Copy, {
|
||||
|
||||
}
|
||||
|
||||
fn get_clone<Vr: WithVarsRead>(&self, vars: &Vr) -> T {
|
||||
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a T> {
|
||||
self.get_new(vars)
|
||||
}
|
||||
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
fn copy_new<Vw: WithVars>(&self, vars: &Vw) -> Option<T>
|
||||
where
|
||||
T: Copy, {
|
||||
self.copy_new(vars)
|
||||
}
|
||||
|
||||
fn clone_new<Vw: WithVars>(&self, vars: &Vw) -> Option<T> {
|
||||
self.clone_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> T {
|
||||
match Rc::try_unwrap(self.0) {
|
||||
Ok(v) => v.value.into_inner(),
|
||||
Err(v) => RcVar(v).get_clone(vars),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.is_new(vars)
|
||||
}
|
||||
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
#[inline]
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.version(vars)
|
||||
}
|
||||
|
||||
fn is_read_only(&self, _: &Vars) -> bool {
|
||||
#[inline]
|
||||
fn is_read_only<Vw: WithVars>(&self, _: &Vw) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn always_read_only(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn can_update(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn modify<M>(&self, vars: &Vars, modify: M) -> Result<(), VarIsReadOnly>
|
||||
#[inline]
|
||||
fn modify<Vw, M>(&self, vars: &Vw, modify: M) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
M: FnOnce(&mut VarModify<T>) + 'static,
|
||||
{
|
||||
self.modify(vars, modify);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
#[inline]
|
||||
fn set<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
{
|
||||
self.set(vars, new_value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
#[inline]
|
||||
fn set_ne<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
T: PartialEq,
|
||||
{
|
||||
Ok(self.set_ne(vars, new_value))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
}
|
||||
}
|
||||
impl<T: VarValue> IntoVar<T> for RcVar<T> {
|
||||
type Var = Self;
|
||||
|
||||
#[inline]
|
||||
fn into_var(self) -> Self::Var {
|
||||
self
|
||||
}
|
||||
|
@ -308,7 +371,7 @@ impl<T: VarValue> fmt::Debug for Response<T> {
|
|||
impl<T: VarValue> ResponseVar<T> {
|
||||
/// References the response value if a response was set.
|
||||
#[inline]
|
||||
pub fn response<'a>(&'a self, vars: &'a VarsRead) -> Option<&'a T> {
|
||||
pub fn rsp<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> Option<&'a T> {
|
||||
match self.get(vars) {
|
||||
Response::Waiting => None,
|
||||
Response::Done(r) => Some(r),
|
||||
|
@ -316,7 +379,7 @@ impl<T: VarValue> ResponseVar<T> {
|
|||
}
|
||||
|
||||
/// References the response value if a response was set for this update.
|
||||
pub fn response_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a T> {
|
||||
pub fn rsp_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a T> {
|
||||
if let Some(new) = self.get_new(vars) {
|
||||
match new {
|
||||
Response::Waiting => None,
|
||||
|
@ -326,6 +389,58 @@ impl<T: VarValue> ResponseVar<T> {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// If the variable contains a response.
|
||||
#[inline]
|
||||
pub fn responded<Vr: WithVarsRead>(&self, vars: &Vr) -> bool {
|
||||
vars.with(|vars| self.rsp(vars).is_some())
|
||||
}
|
||||
|
||||
/// Copy the response value if a response was set.
|
||||
#[inline]
|
||||
pub fn rsp_copy<Vr: WithVarsRead>(&self, vars: &Vr) -> Option<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
vars.with(|vars| self.rsp(vars).copied())
|
||||
}
|
||||
|
||||
/// Clone the response value if a response was set.
|
||||
#[inline]
|
||||
pub fn rsp_clone<Vr: WithVarsRead>(&self, vars: &Vr) -> Option<T> {
|
||||
vars.with(|vars| self.rsp(vars).cloned())
|
||||
}
|
||||
|
||||
/// Copy the response value if a response was set for this update.
|
||||
#[inline]
|
||||
pub fn rsp_new_copy<Vw: WithVars>(self, vars: &Vw) -> Option<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
vars.with(|vars| self.rsp_new(vars).copied())
|
||||
}
|
||||
|
||||
/// Clone the response value if a response was set for this update.
|
||||
#[inline]
|
||||
pub fn rsp_new_clone<Vw: WithVars>(self, vars: &Vw) -> Option<T> {
|
||||
vars.with(|vars| self.rsp_new(vars).cloned())
|
||||
}
|
||||
|
||||
/// If the variable has responded returns the response value or a clone of it if `self` is not the only reference to the response.
|
||||
/// If the variable has **not** responded returns `self` in the error.
|
||||
#[inline]
|
||||
pub fn try_into_rsp<Vr: WithVarsRead>(self, vars: &Vr) -> Result<T, Self> {
|
||||
vars.with(|vars| {
|
||||
if self.responded(vars) {
|
||||
match self.into_value(vars) {
|
||||
Response::Done(r) => Ok(r),
|
||||
Response::Waiting => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
Err(self)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: VarValue> ResponderVar<T> {
|
||||
|
@ -335,11 +450,13 @@ impl<T: VarValue> ResponderVar<T> {
|
|||
///
|
||||
/// Panics if the variable is already in the done state.
|
||||
#[inline]
|
||||
pub fn respond<'a>(&'a self, vars: &'a Vars, response: T) {
|
||||
if let Response::Done(_) = self.get(vars) {
|
||||
panic!("already responded");
|
||||
}
|
||||
self.set(vars, Response::Done(response));
|
||||
pub fn respond<'a, Vw: WithVars>(&'a self, vars: &'a Vw, response: T) {
|
||||
vars.with(|vars| {
|
||||
if let Response::Done(_) = self.get(vars) {
|
||||
panic!("already responded");
|
||||
}
|
||||
self.set(vars, Response::Done(response));
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a [`ResponseVar`] linked to this responder.
|
||||
|
|
|
@ -34,25 +34,33 @@ where
|
|||
{
|
||||
type AsReadOnly = Self;
|
||||
|
||||
type AsLocal = ReadOnlyVar<T, V::AsLocal>;
|
||||
|
||||
#[inline]
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a T {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a T {
|
||||
self.0.get(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a T> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a T> {
|
||||
self.0.get_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
self.0.is_new(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> T {
|
||||
self.0.into_value(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
self.0.version(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_only(&self, _: &Vars) -> bool {
|
||||
fn is_read_only<Vw: WithVars>(&self, _: &Vw) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
|
@ -67,24 +75,27 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn modify<M>(&self, _: &Vars, _: M) -> Result<(), VarIsReadOnly>
|
||||
fn modify<Vw, M>(&self, _: &Vw, _: M) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
M: FnOnce(&mut VarModify<T>) + 'static,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set<N>(&self, _: &Vars, _: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, _: &Vw, _: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
{
|
||||
Err(VarIsReadOnly)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_ne<N>(&self, _: &Vars, _: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, _: &Vw, _: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<T>,
|
||||
T: PartialEq,
|
||||
{
|
||||
|
@ -95,11 +106,6 @@ where
|
|||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
ReadOnlyVar::new(Var::into_local(self.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, V> IntoVar<T> for ReadOnlyVar<T, V>
|
||||
|
@ -114,24 +120,3 @@ where
|
|||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, V> VarLocal<T> for ReadOnlyVar<T, V>
|
||||
where
|
||||
T: VarValue,
|
||||
V: Var<T> + VarLocal<T>,
|
||||
{
|
||||
#[inline]
|
||||
fn get_local(&self) -> &T {
|
||||
self.0.get_local()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn init_local<'a>(&'a mut self, vars: &'a Vars) -> &'a T {
|
||||
self.0.init_local(vars)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update_local<'a>(&'a mut self, vars: &'a Vars) -> Option<&'a T> {
|
||||
self.0.update_local(vars)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,16 +139,16 @@ macro_rules! impl_rc_switch_var {
|
|||
Var<O> for $RcSwitchVar<O, $($V,)+ VI> {
|
||||
type AsReadOnly = ReadOnlyVar<O, Self>;
|
||||
|
||||
type AsLocal = CloningLocalVar<O, Self>;
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a O {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a O {
|
||||
let vars = vars.as_ref();
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.get(vars),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a O> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a O> {
|
||||
let vars = vars.as_ref();
|
||||
if self.is_new(vars) {
|
||||
Some(self.get(vars))
|
||||
} else {
|
||||
|
@ -156,16 +156,33 @@ macro_rules! impl_rc_switch_var {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
self.0.index.is_new(vars)
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> O {
|
||||
match Rc::try_unwrap(self.0) {
|
||||
Ok(r) => {
|
||||
vars.with(move |vars| {
|
||||
match *r.index.get(vars) {
|
||||
$($n => r.vars.$n.into_value(vars),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
})
|
||||
},
|
||||
Err(e) => $RcSwitchVar(e).get_clone(vars)
|
||||
}
|
||||
}
|
||||
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| {
|
||||
self.0.index.is_new(vars)
|
||||
|| match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.is_new(vars),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
let i_ver = self.0.index.version(vars);
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|vars| {
|
||||
let i_ver = self.0.index.version(vars);
|
||||
let var_vers = ($(self.0.vars.$n.version(vars)),+);
|
||||
|
||||
if i_ver != self.0.index_version.get() || $(var_vers.$n != self.0.versions[$n].get())||+ {
|
||||
|
@ -175,56 +192,69 @@ macro_rules! impl_rc_switch_var {
|
|||
}
|
||||
|
||||
self.0.self_version.get()
|
||||
})
|
||||
}
|
||||
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.is_read_only(vars),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| {
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.is_read_only(vars),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn always_read_only(&self) -> bool {
|
||||
$(self.0.vars.$n.always_read_only())&&+
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn can_update(&self) -> bool {
|
||||
// you could make one that doesn't but we don't care.
|
||||
true
|
||||
}
|
||||
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<O>
|
||||
{
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.set(vars, new_value),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
vars.with(|vars| {
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.set(vars, new_value),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<O>,
|
||||
O : PartialEq
|
||||
{
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.set_ne(vars, new_value),)+
|
||||
_ => panic!("switch_var index out of range")
|
||||
}
|
||||
vars.with(|vars| {
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.set_ne(vars, new_value),)+
|
||||
_ => panic!("switch_var index out of range")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn modify<F: FnOnce(&mut VarModify<O>) + 'static>(&self, vars: &Vars, change: F) -> Result<(), VarIsReadOnly> {
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.modify(vars, change),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
fn modify<Vw, F>(&self, vars: &Vw, change: F) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
F: FnOnce(&mut VarModify<O>) + 'static
|
||||
{
|
||||
vars.with(|vars| {
|
||||
match *self.0.index.get(vars) {
|
||||
$($n => self.0.vars.$n.modify(vars, change),)+
|
||||
_ => panic!("switch_var index out of range"),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
@ -233,6 +263,8 @@ macro_rules! impl_rc_switch_var {
|
|||
impl<O: VarValue, $($V: Var<O>,)+ VI: Var<usize>>
|
||||
IntoVar<O> for $RcSwitchVar<O, $($V,)+ VI> {
|
||||
type Var = Self;
|
||||
|
||||
#[inline]
|
||||
fn into_var(self) -> Self {
|
||||
self
|
||||
}
|
||||
|
@ -337,13 +369,13 @@ impl<O: VarValue, VI: Var<usize>> Clone for RcSwitchVar<O, VI> {
|
|||
impl<O: VarValue, VI: Var<usize>> Var<O> for RcSwitchVar<O, VI> {
|
||||
type AsReadOnly = ReadOnlyVar<O, Self>;
|
||||
|
||||
type AsLocal = CloningLocalVar<O, Self>;
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a O {
|
||||
self.0.vars[*self.0.index.get(vars)].get(vars)
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a O {
|
||||
let vars = vars.as_ref();
|
||||
self.0.vars[self.0.index.copy(vars)].get(vars)
|
||||
}
|
||||
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a O> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a O> {
|
||||
let vars = vars.as_ref();
|
||||
if self.is_new(vars) {
|
||||
Some(self.get(vars))
|
||||
} else {
|
||||
|
@ -351,68 +383,77 @@ impl<O: VarValue, VI: Var<usize>> Var<O> for RcSwitchVar<O, VI> {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
self.0.vars[*self.0.index.get(vars)].is_new(vars)
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| self.0.vars[self.0.index.copy(vars)].is_new(vars))
|
||||
}
|
||||
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
let mut changed = false;
|
||||
|
||||
let i_ver = self.0.index.version(vars);
|
||||
if i_ver != self.0.index_version.get() {
|
||||
self.0.index_version.set(i_ver);
|
||||
changed = true;
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> O {
|
||||
match Rc::try_unwrap(self.0) {
|
||||
Ok(r) => vars.with(move |vars| Vec::from(r.vars).swap_remove(r.index.copy(vars)).into_value(vars)),
|
||||
Err(e) => RcSwitchVar(e).get_clone(vars),
|
||||
}
|
||||
|
||||
let i = *self.0.index.get(vars);
|
||||
let v_ver = self.0.vars[i].version(vars);
|
||||
if v_ver != self.0.var_versions[i].get() {
|
||||
self.0.var_versions[i].set(v_ver);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if changed {
|
||||
self.0.self_version.set(self.0.self_version.get().wrapping_add(1));
|
||||
}
|
||||
|
||||
self.0.self_version.get()
|
||||
}
|
||||
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
self.0.vars[*self.0.index.get(vars)].is_read_only(vars)
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|vars| {
|
||||
let mut changed = false;
|
||||
|
||||
let i_ver = self.0.index.version(vars);
|
||||
if i_ver != self.0.index_version.get() {
|
||||
self.0.index_version.set(i_ver);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
let i = *self.0.index.get(vars);
|
||||
let v_ver = self.0.vars[i].version(vars);
|
||||
if v_ver != self.0.var_versions[i].get() {
|
||||
self.0.var_versions[i].set(v_ver);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if changed {
|
||||
self.0.self_version.set(self.0.self_version.get().wrapping_add(1));
|
||||
}
|
||||
|
||||
self.0.self_version.get()
|
||||
})
|
||||
}
|
||||
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| self.0.vars[*self.0.index.get(vars)].is_read_only(vars))
|
||||
}
|
||||
|
||||
fn always_read_only(&self) -> bool {
|
||||
self.0.vars.iter().all(|v| v.always_read_only())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn can_update(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<O>,
|
||||
{
|
||||
self.0.vars[*self.0.index.get(vars)].set(vars, new_value)
|
||||
vars.with(|vars| self.0.vars[*self.0.index.get(vars)].set(vars, new_value))
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<O>,
|
||||
O: PartialEq,
|
||||
{
|
||||
self.0.vars[*self.0.index.get(vars)].set_ne(vars, new_value)
|
||||
vars.with(|vars| self.0.vars[*self.0.index.get(vars)].set_ne(vars, new_value))
|
||||
}
|
||||
|
||||
fn modify<F: FnOnce(&mut VarModify<O>) + 'static>(&self, vars: &Vars, change: F) -> Result<(), VarIsReadOnly> {
|
||||
self.0.vars[*self.0.index.get(vars)].modify(vars, change)
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
fn modify<Vw: WithVars, F: FnOnce(&mut VarModify<O>) + 'static>(&self, vars: &Vw, change: F) -> Result<(), VarIsReadOnly> {
|
||||
vars.with(|vars| self.0.vars[*self.0.index.get(vars)].modify(vars, change))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
@ -420,6 +461,7 @@ impl<O: VarValue, VI: Var<usize>> Var<O> for RcSwitchVar<O, VI> {
|
|||
impl<O: VarValue, VI: Var<usize>> IntoVar<O> for RcSwitchVar<O, VI> {
|
||||
type Var = Self;
|
||||
|
||||
#[inline]
|
||||
fn into_var(self) -> Self::Var {
|
||||
self
|
||||
}
|
||||
|
|
|
@ -611,6 +611,240 @@ impl Deref for Vars {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents a type that can provide access to a [`Vars`] inside the window of function call.
|
||||
///
|
||||
/// This is used to make vars assign less cumbersome to use, it is implemented to all sync and async context types and [`Vars`] it-self.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// The example demonstrate how this `trait` simplifies calls to [`Var::set`]. The same applies to [`Var::modify`] and [`Var::set_ne`].
|
||||
///
|
||||
/// ```
|
||||
/// # use zero_ui_core::{var::*, context::*};
|
||||
/// # struct Foo { foo_var: RcVar<&'static str> } impl Foo {
|
||||
/// fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
/// self.foo_var.set(ctx, "we are not borrowing `ctx` so can use it directly");
|
||||
///
|
||||
/// // ..
|
||||
/// let services = ctx.services;
|
||||
/// self.foo_var.set(ctx.vars, "we are partially borrowing `ctx` but not `ctx.vars` so we use that");
|
||||
/// }
|
||||
///
|
||||
/// async fn handler(&mut self, ctx: WidgetContextMut) {
|
||||
/// self.foo_var.set(&ctx, "async contexts are also almost seamless");
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
pub trait WithVars {
|
||||
/// Calls `action` with the [`Vars`] reference.
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&Vars) -> R;
|
||||
}
|
||||
impl WithVars for Vars {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&Vars) -> R,
|
||||
{
|
||||
action(self)
|
||||
}
|
||||
}
|
||||
impl<'a, 'w> WithVars for crate::context::AppContext<'a, 'w> {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&Vars) -> R,
|
||||
{
|
||||
action(self.vars)
|
||||
}
|
||||
}
|
||||
impl<'a> WithVars for crate::context::WindowContext<'a> {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&Vars) -> R,
|
||||
{
|
||||
action(self.vars)
|
||||
}
|
||||
}
|
||||
impl<'a> WithVars for crate::context::WidgetContext<'a> {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&Vars) -> R,
|
||||
{
|
||||
action(self.vars)
|
||||
}
|
||||
}
|
||||
impl WithVars for crate::context::AppContextMut {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&Vars) -> R,
|
||||
{
|
||||
self.with(move |ctx| action(ctx.vars))
|
||||
}
|
||||
}
|
||||
impl WithVars for crate::context::WindowContextMut {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&Vars) -> R,
|
||||
{
|
||||
self.with(move |ctx| action(ctx.vars))
|
||||
}
|
||||
}
|
||||
impl WithVars for crate::context::WidgetContextMut {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&Vars) -> R,
|
||||
{
|
||||
self.with(move |ctx| action(ctx.vars))
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a type that can provide access to a [`VarsRead`] inside the window of function call.
|
||||
///
|
||||
/// This is used to make vars value-read less cumbersome to use, it is implemented to all sync and async context
|
||||
/// types and [`Vars`] it-self.
|
||||
pub trait WithVarsRead {
|
||||
/// Calls `action` with the [`Vars`] reference.
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R;
|
||||
}
|
||||
impl WithVarsRead for Vars {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
action(self)
|
||||
}
|
||||
}
|
||||
impl WithVarsRead for VarsRead {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
action(self)
|
||||
}
|
||||
}
|
||||
impl<'a, 'w> WithVarsRead for crate::context::AppContext<'a, 'w> {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
action(self.vars)
|
||||
}
|
||||
}
|
||||
impl<'a> WithVarsRead for crate::context::WindowContext<'a> {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
action(self.vars)
|
||||
}
|
||||
}
|
||||
impl<'a> WithVarsRead for crate::context::WidgetContext<'a> {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
action(self.vars)
|
||||
}
|
||||
}
|
||||
impl WithVarsRead for crate::context::AppContextMut {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
self.with(move |ctx| action(ctx.vars))
|
||||
}
|
||||
}
|
||||
impl WithVarsRead for crate::context::WindowContextMut {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
self.with(move |ctx| action(ctx.vars))
|
||||
}
|
||||
}
|
||||
impl WithVarsRead for crate::context::WidgetContextMut {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
self.with(move |ctx| action(ctx.vars))
|
||||
}
|
||||
}
|
||||
impl<'a> WithVarsRead for crate::context::LayoutContext<'a> {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
action(self.vars)
|
||||
}
|
||||
}
|
||||
impl<'a> WithVarsRead for crate::context::RenderContext<'a> {
|
||||
fn with<R, A>(&self, action: A) -> R
|
||||
where
|
||||
A: FnOnce(&VarsRead) -> R,
|
||||
{
|
||||
action(self.vars)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<VarsRead> for VarsRead {
|
||||
fn as_ref(&self) -> &VarsRead {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl AsRef<VarsRead> for Vars {
|
||||
fn as_ref(&self) -> &VarsRead {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<'a, 'w> AsRef<VarsRead> for crate::context::AppContext<'a, 'w> {
|
||||
fn as_ref(&self) -> &VarsRead {
|
||||
self.vars
|
||||
}
|
||||
}
|
||||
impl<'a> AsRef<VarsRead> for crate::context::WindowContext<'a> {
|
||||
fn as_ref(&self) -> &VarsRead {
|
||||
self.vars
|
||||
}
|
||||
}
|
||||
impl<'a> AsRef<VarsRead> for crate::context::WidgetContext<'a> {
|
||||
fn as_ref(&self) -> &VarsRead {
|
||||
self.vars
|
||||
}
|
||||
}
|
||||
impl<'a> AsRef<VarsRead> for crate::context::LayoutContext<'a> {
|
||||
fn as_ref(&self) -> &VarsRead {
|
||||
self.vars
|
||||
}
|
||||
}
|
||||
impl<'a> AsRef<VarsRead> for crate::context::RenderContext<'a> {
|
||||
fn as_ref(&self) -> &VarsRead {
|
||||
self.vars
|
||||
}
|
||||
}
|
||||
impl AsRef<Vars> for Vars {
|
||||
fn as_ref(&self) -> &Vars {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl<'a, 'w> AsRef<Vars> for crate::context::AppContext<'a, 'w> {
|
||||
fn as_ref(&self) -> &Vars {
|
||||
self.vars
|
||||
}
|
||||
}
|
||||
impl<'a> AsRef<Vars> for crate::context::WindowContext<'a> {
|
||||
fn as_ref(&self) -> &Vars {
|
||||
self.vars
|
||||
}
|
||||
}
|
||||
impl<'a> AsRef<Vars> for crate::context::WidgetContext<'a> {
|
||||
fn as_ref(&self) -> &Vars {
|
||||
self.vars
|
||||
}
|
||||
}
|
||||
|
||||
/// A variable update receiver that can be used from any thread and without access to [`Vars`].
|
||||
///
|
||||
/// Use [`VarsRead::receiver`] to create a receiver, drop to stop listening.
|
||||
|
@ -806,9 +1040,9 @@ impl<T: VarValue + Send> ResponseSender<T> {
|
|||
}
|
||||
|
||||
/// New paired [`ResponseSender`] and [`ResponseVar`] in the waiting state.
|
||||
pub fn response_channel<T: VarValue + Send>(vars: &Vars) -> (ResponseSender<T>, ResponseVar<T>) {
|
||||
pub fn response_channel<T: VarValue + Send, Vw: WithVars>(vars: &Vw) -> (ResponseSender<T>, ResponseVar<T>) {
|
||||
let (responder, response) = response_var();
|
||||
(vars.sender(&responder), response)
|
||||
vars.with(|vars| (vars.sender(&responder), response))
|
||||
}
|
||||
|
||||
/// Represents a variable binding created one of the `bind` methods of [`Vars`].
|
||||
|
@ -900,8 +1134,8 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&20i32), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&"20".to_text()), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(20i32), a.copy_new(ctx));
|
||||
assert_eq!(Some("20".to_text()), b.copy_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -913,8 +1147,8 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&13i32), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&"13".to_text()), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(13i32), a.copy_new(ctx));
|
||||
assert_eq!(Some("13".to_text()), b.get_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -948,8 +1182,8 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&20i32), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&"20".to_text()), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(20i32), a.copy_new(ctx));
|
||||
assert_eq!(Some("20".to_text()), b.get_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -961,8 +1195,8 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&"55".to_text()), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(&55i32), a.get_new(ctx.vars));
|
||||
assert_eq!(Some("55".to_text()), b.get_new(ctx));
|
||||
assert_eq!(Some(55i32), a.copy_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -996,8 +1230,8 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&20i32), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&"20".to_text()), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(20i32), a.copy_new(ctx));
|
||||
assert_eq!(Some("20".to_text()), b.clone_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1009,9 +1243,9 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&13i32), a.get_new(ctx.vars));
|
||||
assert_eq!(&"20".to_text(), b.get(ctx.vars));
|
||||
assert!(!b.is_new(ctx.vars));
|
||||
assert_eq!(Some(&13i32), a.get_new(ctx));
|
||||
assert_eq!("20".to_text(), b.get(ctx));
|
||||
assert!(!b.is_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1045,8 +1279,8 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&20i32), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&"20".to_text()), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(20i32), a.get_new(ctx));
|
||||
assert_eq!(Some("20".to_text()), b.get_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1058,8 +1292,8 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&"55".to_text()), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(&55i32), a.get_new(ctx.vars));
|
||||
assert_eq!(Some("55".to_text()), b.get_new(ctx));
|
||||
assert_eq!(Some(55i32), a.get_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1071,9 +1305,9 @@ mod tests {
|
|||
app.update_observe(
|
||||
|ctx| {
|
||||
update_count += 1;
|
||||
assert_eq!(Some(&"not a i32".to_text()), b.get_new(ctx.vars));
|
||||
assert_eq!(&55i32, a.get(ctx.vars));
|
||||
assert!(!a.is_new(ctx.vars));
|
||||
assert_eq!(Some("not a i32".to_text()), b.get_new(ctx));
|
||||
assert_eq!(55i32, a.get(ctx));
|
||||
assert!(!a.is_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1109,10 +1343,10 @@ mod tests {
|
|||
|ctx| {
|
||||
update_count += 1;
|
||||
|
||||
assert_eq!(Some(&20), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&21), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(&22), c.get_new(ctx.vars));
|
||||
assert_eq!(Some(&23), d.get_new(ctx.vars));
|
||||
assert_eq!(Some(20), a.copy_new(ctx));
|
||||
assert_eq!(Some(21), b.copy_new(ctx));
|
||||
assert_eq!(Some(22), c.copy_new(ctx));
|
||||
assert_eq!(Some(23), d.copy_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1125,10 +1359,10 @@ mod tests {
|
|||
|ctx| {
|
||||
update_count += 1;
|
||||
|
||||
assert_eq!(Some(&30), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&31), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(&32), c.get_new(ctx.vars));
|
||||
assert_eq!(Some(&33), d.get_new(ctx.vars));
|
||||
assert_eq!(Some(30), a.copy_new(ctx));
|
||||
assert_eq!(Some(31), b.copy_new(ctx));
|
||||
assert_eq!(Some(32), c.copy_new(ctx));
|
||||
assert_eq!(Some(33), d.copy_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1164,10 +1398,10 @@ mod tests {
|
|||
|ctx| {
|
||||
update_count += 1;
|
||||
|
||||
assert_eq!(Some(&20), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&20), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(&20), c.get_new(ctx.vars));
|
||||
assert_eq!(Some(&20), d.get_new(ctx.vars));
|
||||
assert_eq!(Some(20), a.copy_new(ctx));
|
||||
assert_eq!(Some(20), b.copy_new(ctx));
|
||||
assert_eq!(Some(20), c.copy_new(ctx));
|
||||
assert_eq!(Some(20), d.copy_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1180,10 +1414,10 @@ mod tests {
|
|||
|ctx| {
|
||||
update_count += 1;
|
||||
|
||||
assert_eq!(Some(&30), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&30), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(&30), c.get_new(ctx.vars));
|
||||
assert_eq!(Some(&30), d.get_new(ctx.vars));
|
||||
assert_eq!(Some(30), a.copy_new(ctx));
|
||||
assert_eq!(Some(30), b.copy_new(ctx));
|
||||
assert_eq!(Some(30), c.copy_new(ctx));
|
||||
assert_eq!(Some(30), d.copy_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1209,8 +1443,8 @@ mod tests {
|
|||
|ctx| {
|
||||
update_count += 1;
|
||||
|
||||
assert_eq!(Some(&10), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&11), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(10), a.copy_new(ctx));
|
||||
assert_eq!(Some(11), b.copy_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1226,9 +1460,9 @@ mod tests {
|
|||
|ctx| {
|
||||
update_count += 1;
|
||||
|
||||
assert_eq!(Some(&100), a.get_new(ctx.vars));
|
||||
assert!(!b.is_new(ctx.vars));
|
||||
assert_eq!(&11, b.get(ctx.vars));
|
||||
assert_eq!(Some(100), a.copy_new(ctx));
|
||||
assert!(!b.is_new(ctx));
|
||||
assert_eq!(11, b.copy(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1251,8 +1485,8 @@ mod tests {
|
|||
|ctx| {
|
||||
update_count += 1;
|
||||
|
||||
assert_eq!(Some(&10), a.get_new(ctx.vars));
|
||||
assert_eq!(Some(&11), b.get_new(ctx.vars));
|
||||
assert_eq!(Some(10), a.copy_new(ctx));
|
||||
assert_eq!(Some(11), b.copy_new(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
@ -1267,9 +1501,9 @@ mod tests {
|
|||
|ctx| {
|
||||
update_count += 1;
|
||||
|
||||
assert_eq!(Some(&100), a.get_new(ctx.vars));
|
||||
assert!(!b.is_new(ctx.vars));
|
||||
assert_eq!(&11, b.get(ctx.vars));
|
||||
assert_eq!(Some(100), a.copy_new(ctx));
|
||||
assert!(!b.is_new(ctx));
|
||||
assert_eq!(11, b.copy(ctx));
|
||||
},
|
||||
false,
|
||||
);
|
||||
|
|
|
@ -140,9 +140,9 @@ macro_rules! impl_rc_when_var {
|
|||
impl<O: VarValue, D: Var<O>, $($C: Var<bool>),+ , $($V: Var<O>),+> Var<O> for $RcMergeVar<O, D, $($C),+ , $($V),+> {
|
||||
type AsReadOnly = ReadOnlyVar<O, Self>;
|
||||
|
||||
type AsLocal = CloningLocalVar<O, Self>;
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a O {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a O {
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.get(vars)
|
||||
|
@ -152,7 +152,9 @@ macro_rules! impl_rc_when_var {
|
|||
self.0.default_value.get(vars)
|
||||
}
|
||||
}
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a O> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a O> {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
let mut condition_is_new = false;
|
||||
$(
|
||||
condition_is_new |= self.0.conditions.$n.is_new(vars);
|
||||
|
@ -171,107 +173,134 @@ macro_rules! impl_rc_when_var {
|
|||
self.0.default_value.get_new(vars)
|
||||
}
|
||||
}
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
let mut condition_is_new = false;
|
||||
|
||||
$(
|
||||
condition_is_new |= self.0.conditions.$n.is_new(vars);
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
return condition_is_new || self.0.values.$n.is_new(vars);
|
||||
}
|
||||
)+
|
||||
condition_is_new || self.0.default_value.is_new(vars)
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> O {
|
||||
match Rc::try_unwrap(self.0) {
|
||||
Ok(r) => vars.with(|vars| {
|
||||
$(
|
||||
if *r.conditions.$n.get(vars) {
|
||||
r.values.$n.into_value(vars)
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
r.default_value.into_value(vars)
|
||||
}
|
||||
}),
|
||||
Err(e) => $RcMergeVar(e).get_clone(vars)
|
||||
}
|
||||
}
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
let mut changed = false;
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| {
|
||||
let mut condition_is_new = false;
|
||||
|
||||
$(
|
||||
let version = self.0.conditions.$n.version(vars);
|
||||
if version != self.0.condition_versions[$n].get() {
|
||||
changed = true;
|
||||
self.0.condition_versions[$n].set(version);
|
||||
}
|
||||
)+
|
||||
|
||||
$(
|
||||
let version = self.0.values.$n.version(vars);
|
||||
if version != self.0.value_versions[$n].get() {
|
||||
changed = true;
|
||||
self.0.value_versions[$n].set(version);
|
||||
}
|
||||
)+
|
||||
|
||||
let version = self.0.default_value.version(vars);
|
||||
if version != self.0.default_version.get() {
|
||||
changed = true;
|
||||
self.0.default_version.set(version);
|
||||
}
|
||||
|
||||
if changed {
|
||||
self.0.self_version.set(self.0.self_version.get().wrapping_add(1));
|
||||
}
|
||||
|
||||
self.0.self_version.get()
|
||||
$(
|
||||
condition_is_new |= self.0.conditions.$n.is_new(vars);
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
return condition_is_new || self.0.values.$n.is_new(vars);
|
||||
}
|
||||
)+
|
||||
condition_is_new || self.0.default_value.is_new(vars)
|
||||
})
|
||||
}
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.is_read_only(vars)
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|vars| {
|
||||
let mut changed = false;
|
||||
|
||||
$(
|
||||
let version = self.0.conditions.$n.version(vars);
|
||||
if version != self.0.condition_versions[$n].get() {
|
||||
changed = true;
|
||||
self.0.condition_versions[$n].set(version);
|
||||
}
|
||||
)+
|
||||
|
||||
$(
|
||||
let version = self.0.values.$n.version(vars);
|
||||
if version != self.0.value_versions[$n].get() {
|
||||
changed = true;
|
||||
self.0.value_versions[$n].set(version);
|
||||
}
|
||||
)+
|
||||
|
||||
let version = self.0.default_value.version(vars);
|
||||
if version != self.0.default_version.get() {
|
||||
changed = true;
|
||||
self.0.default_version.set(version);
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
self.0.default_value.is_read_only(vars)
|
||||
}
|
||||
|
||||
if changed {
|
||||
self.0.self_version.set(self.0.self_version.get().wrapping_add(1));
|
||||
}
|
||||
|
||||
self.0.self_version.get()
|
||||
})
|
||||
}
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| {
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.is_read_only(vars)
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
self.0.default_value.is_read_only(vars)
|
||||
}
|
||||
})
|
||||
}
|
||||
fn always_read_only(&self) -> bool {
|
||||
$(self.0.values.$n.always_read_only())&&+ && self.0.default_value.always_read_only()
|
||||
}
|
||||
#[inline]
|
||||
fn can_update(&self) -> bool {
|
||||
true
|
||||
}
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<O>
|
||||
{
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.set(vars, new_value)
|
||||
vars.with(|vars| {
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.set(vars, new_value)
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
self.0.default_value.set(vars, new_value)
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
self.0.default_value.set(vars, new_value)
|
||||
}
|
||||
})
|
||||
}
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<O>,
|
||||
O: PartialEq
|
||||
{
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.set_ne(vars, new_value)
|
||||
vars.with(|vars| {
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.set_ne(vars, new_value)
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
self.0.default_value.set_ne(vars, new_value)
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
self.0.default_value.set_ne(vars, new_value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn modify<F: FnOnce(&mut VarModify<O>) + 'static>(&self, vars: &Vars, change: F) -> Result<(), VarIsReadOnly> {
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.modify(vars, change)
|
||||
fn modify<Vw: WithVars, F: FnOnce(&mut VarModify<O>) + 'static>(&self, vars: &Vw, change: F) -> Result<(), VarIsReadOnly> {
|
||||
vars.with(|vars| {
|
||||
$(
|
||||
if *self.0.conditions.$n.get(vars) {
|
||||
self.0.values.$n.modify(vars, change)
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
self.0.default_value.modify(vars, change)
|
||||
}
|
||||
)else+
|
||||
else {
|
||||
self.0.default_value.modify(vars, change)
|
||||
}
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
@ -280,6 +309,7 @@ macro_rules! impl_rc_when_var {
|
|||
impl<O: VarValue, D: Var<O>, $($C: Var<bool>),+ , $($V: Var<O>),+> IntoVar<O> for $RcMergeVar<O, D, $($C),+ , $($V),+> {
|
||||
type Var = Self;
|
||||
|
||||
#[inline]
|
||||
fn into_var(self) -> Self::Var {
|
||||
self
|
||||
}
|
||||
|
@ -334,10 +364,11 @@ impl<O: VarValue> Clone for RcWhenVar<O> {
|
|||
}
|
||||
impl<O: VarValue> Var<O> for RcWhenVar<O> {
|
||||
type AsReadOnly = ReadOnlyVar<O, Self>;
|
||||
type AsLocal = CloningLocalVar<O, Self>;
|
||||
|
||||
/// Gets the the first variable with `true` condition or the default variable.
|
||||
fn get<'a>(&'a self, vars: &'a VarsRead) -> &'a O {
|
||||
fn get<'a, Vr: AsRef<VarsRead>>(&'a self, vars: &'a Vr) -> &'a O {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.get(vars);
|
||||
|
@ -353,7 +384,9 @@ impl<O: VarValue> Var<O> for RcWhenVar<O> {
|
|||
/// Gets the default variable if any of the conditions are new and all are `false`.
|
||||
///
|
||||
/// Gets the default variable if all conditions are `false` and the default variable value is new.
|
||||
fn get_new<'a>(&'a self, vars: &'a Vars) -> Option<&'a O> {
|
||||
fn get_new<'a, Vw: AsRef<Vars>>(&'a self, vars: &'a Vw) -> Option<&'a O> {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
let mut condition_is_new = false;
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
condition_is_new |= c.is_new(vars);
|
||||
|
@ -377,57 +410,81 @@ impl<O: VarValue> Var<O> for RcWhenVar<O> {
|
|||
/// Gets if [`get_new`](Self::get_new) will return `Some(_)` if called.
|
||||
///
|
||||
/// This is slightly more performant than `when_var.get_new(vars).is_some()`.
|
||||
fn is_new(&self, vars: &Vars) -> bool {
|
||||
let mut condition_is_new = false;
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
condition_is_new |= c.is_new(vars);
|
||||
if *c.get(vars) {
|
||||
return condition_is_new || v.is_new(vars);
|
||||
fn is_new<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| {
|
||||
let mut condition_is_new = false;
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
condition_is_new |= c.is_new(vars);
|
||||
if *c.get(vars) {
|
||||
return condition_is_new || v.is_new(vars);
|
||||
}
|
||||
}
|
||||
condition_is_new || self.0.default_.is_new(vars)
|
||||
})
|
||||
}
|
||||
|
||||
/// If `self` is the only reference calls `into_value` on the first variable with condition `true`.
|
||||
///
|
||||
/// If `self` is not the only reference returns a clone of the value.
|
||||
fn into_value<Vr: WithVarsRead>(self, vars: &Vr) -> O {
|
||||
match Rc::try_unwrap(self.0) {
|
||||
Ok(r) => vars.with(move |vars| {
|
||||
for (c, v) in Vec::from(r.whens) {
|
||||
if *c.get(vars) {
|
||||
return v.into_value(vars);
|
||||
}
|
||||
}
|
||||
|
||||
r.default_.into_value(vars)
|
||||
}),
|
||||
Err(e) => RcWhenVar(e).get_clone(vars),
|
||||
}
|
||||
condition_is_new || self.0.default_.is_new(vars)
|
||||
}
|
||||
|
||||
/// Gets the version.
|
||||
///
|
||||
/// The version is new when any of the condition and value variables version is new.
|
||||
fn version(&self, vars: &VarsRead) -> u32 {
|
||||
let mut changed = false;
|
||||
fn version<Vr: WithVarsRead>(&self, vars: &Vr) -> u32 {
|
||||
vars.with(|vars| {
|
||||
let mut changed = false;
|
||||
|
||||
let dv = self.0.default_.version(vars);
|
||||
if dv != self.0.default_version.get() {
|
||||
changed = true;
|
||||
self.0.default_version.set(dv);
|
||||
}
|
||||
|
||||
for ((c, v), (w_cv, w_vv)) in self.0.whens.iter().zip(self.0.when_versions.iter()) {
|
||||
let cv = c.version(vars);
|
||||
if cv != w_cv.get() {
|
||||
let dv = self.0.default_.version(vars);
|
||||
if dv != self.0.default_version.get() {
|
||||
changed = true;
|
||||
w_cv.set(cv);
|
||||
self.0.default_version.set(dv);
|
||||
}
|
||||
let vv = v.version(vars);
|
||||
if vv != w_vv.get() {
|
||||
changed = true;
|
||||
w_vv.set(vv);
|
||||
|
||||
for ((c, v), (w_cv, w_vv)) in self.0.whens.iter().zip(self.0.when_versions.iter()) {
|
||||
let cv = c.version(vars);
|
||||
if cv != w_cv.get() {
|
||||
changed = true;
|
||||
w_cv.set(cv);
|
||||
}
|
||||
let vv = v.version(vars);
|
||||
if vv != w_vv.get() {
|
||||
changed = true;
|
||||
w_vv.set(vv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if changed {
|
||||
self.0.self_version.set(self.0.self_version.get().wrapping_add(1));
|
||||
}
|
||||
if changed {
|
||||
self.0.self_version.set(self.0.self_version.get().wrapping_add(1));
|
||||
}
|
||||
|
||||
self.0.self_version.get()
|
||||
self.0.self_version.get()
|
||||
})
|
||||
}
|
||||
|
||||
/// If the [current value variable](Self::get) is read-only.
|
||||
fn is_read_only(&self, vars: &Vars) -> bool {
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.is_read_only(vars);
|
||||
fn is_read_only<Vw: WithVars>(&self, vars: &Vw) -> bool {
|
||||
vars.with(|vars| {
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.is_read_only(vars);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.0.default_.is_read_only(vars)
|
||||
self.0.default_.is_read_only(vars)
|
||||
})
|
||||
}
|
||||
|
||||
/// If all value variables (including default) are always read-only.
|
||||
|
@ -436,50 +493,56 @@ impl<O: VarValue> Var<O> for RcWhenVar<O> {
|
|||
}
|
||||
|
||||
/// Always `true`.
|
||||
#[inline]
|
||||
fn can_update(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Sets the [current value variable](Self::get).
|
||||
fn set<N>(&self, vars: &Vars, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
fn set<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<(), VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<O>,
|
||||
{
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.set(vars, new_value);
|
||||
vars.with(|vars| {
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.set(vars, new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.0.default_.set(vars, new_value)
|
||||
self.0.default_.set(vars, new_value)
|
||||
})
|
||||
}
|
||||
|
||||
fn set_ne<N>(&self, vars: &Vars, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
fn set_ne<Vw, N>(&self, vars: &Vw, new_value: N) -> Result<bool, VarIsReadOnly>
|
||||
where
|
||||
Vw: WithVars,
|
||||
N: Into<O>,
|
||||
O: PartialEq,
|
||||
{
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.set_ne(vars, new_value);
|
||||
vars.with(|vars| {
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.set_ne(vars, new_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.0.default_.set_ne(vars, new_value)
|
||||
self.0.default_.set_ne(vars, new_value)
|
||||
})
|
||||
}
|
||||
|
||||
/// Modify the [current value variable](Self::get).
|
||||
fn modify<F: FnOnce(&mut VarModify<O>) + 'static>(&self, vars: &Vars, change: F) -> Result<(), VarIsReadOnly> {
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.modify(vars, change);
|
||||
fn modify<Vw: WithVars, F: FnOnce(&mut VarModify<O>) + 'static>(&self, vars: &Vw, change: F) -> Result<(), VarIsReadOnly> {
|
||||
vars.with(|vars| {
|
||||
for (c, v) in self.0.whens.iter() {
|
||||
if *c.get(vars) {
|
||||
return v.modify(vars, change);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.0.default_.modify(vars, change)
|
||||
}
|
||||
|
||||
fn into_local(self) -> Self::AsLocal {
|
||||
CloningLocalVar::new(self)
|
||||
self.0.default_.modify(vars, change)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_read_only(self) -> Self::AsReadOnly {
|
||||
ReadOnlyVar::new(self)
|
||||
}
|
||||
|
@ -487,6 +550,7 @@ impl<O: VarValue> Var<O> for RcWhenVar<O> {
|
|||
impl<O: VarValue> IntoVar<O> for RcWhenVar<O> {
|
||||
type Var = Self;
|
||||
|
||||
#[inline]
|
||||
fn into_var(self) -> Self::Var {
|
||||
self
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::{fmt, ops};
|
||||
|
||||
use crate::event::EventUpdateArgs;
|
||||
use crate::var::{context_var, IntoVar, Vars};
|
||||
use crate::var::{context_var, IntoVar, Vars, WithVars, WithVarsRead};
|
||||
use crate::{
|
||||
context::RenderContext,
|
||||
render::{FrameBuilder, FrameUpdate, WidgetInfo, WidgetTransformKey},
|
||||
|
@ -302,14 +302,14 @@ pub struct IsEnabled;
|
|||
impl IsEnabled {
|
||||
/// Gets the enabled state in the current `vars` context.
|
||||
#[inline]
|
||||
pub fn get(vars: &VarsRead) -> bool {
|
||||
*IsEnabledVar::get(vars)
|
||||
pub fn get<Vr: WithVarsRead>(vars: &Vr) -> bool {
|
||||
vars.with(|vars| *IsEnabledVar::get(vars))
|
||||
}
|
||||
|
||||
/// Gets the new enabled state in the current `vars` context.
|
||||
#[inline]
|
||||
pub fn get_new(vars: &Vars) -> Option<bool> {
|
||||
IsEnabledVar::get_new(vars).copied()
|
||||
pub fn get_new<Vw: WithVars>(vars: &Vars) -> Option<bool> {
|
||||
vars.with(|vars| IsEnabledVar::get_new(vars).copied())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,7 +357,7 @@ pub fn enabled(child: impl UiNode, enabled: impl IntoVar<bool>) -> impl UiNode {
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, E: Var<bool>> UiNode for EnabledNode<C, E> {
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
if !*self.enabled.get(ctx.vars) {
|
||||
if !self.enabled.copy(ctx) {
|
||||
ctx.widget_state.set::<EnabledState>(false);
|
||||
}
|
||||
self.with_context(ctx.vars, |c| c.init(ctx));
|
||||
|
@ -368,7 +368,7 @@ pub fn enabled(child: impl UiNode, enabled: impl IntoVar<bool>) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if let Some(&state) = self.enabled.get_new(ctx.vars) {
|
||||
if let Some(&state) = self.enabled.get_new(ctx) {
|
||||
ctx.widget_state.set::<EnabledState>(state);
|
||||
ctx.updates.render(); // TODO meta updates without a new frame?
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ pub fn enabled(child: impl UiNode, enabled: impl IntoVar<bool>) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
if !*self.enabled.get(ctx.vars) {
|
||||
if !self.enabled.copy(ctx) {
|
||||
frame.meta().set::<EnabledState>(false);
|
||||
}
|
||||
self.child.render(ctx, frame);
|
||||
|
@ -435,7 +435,7 @@ pub fn visibility(child: impl UiNode, visibility: impl IntoVar<Visibility>) -> i
|
|||
}
|
||||
impl<C: UiNode, V: Var<Visibility>> UiNode for VisibilityNode<C, V> {
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
let vis = *self.visibility.get(ctx.vars);
|
||||
let vis = self.visibility.copy(ctx);
|
||||
ctx.widget_state.set::<VisibilityState>(vis);
|
||||
|
||||
self.with_context(ctx.vars, |c| c.init(ctx));
|
||||
|
@ -446,7 +446,7 @@ pub fn visibility(child: impl UiNode, visibility: impl IntoVar<Visibility>) -> i
|
|||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if let Some(&vis) = self.visibility.get_new(ctx.vars) {
|
||||
if let Some(&vis) = self.visibility.get_new(ctx) {
|
||||
ctx.widget_state.set::<VisibilityState>(vis);
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
@ -454,14 +454,14 @@ pub fn visibility(child: impl UiNode, visibility: impl IntoVar<Visibility>) -> i
|
|||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
match *self.visibility.get(ctx.vars) {
|
||||
match self.visibility.copy(ctx) {
|
||||
Visibility::Visible | Visibility::Hidden => self.child.measure(ctx, available_size),
|
||||
Visibility::Collapsed => LayoutSize::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
if let Visibility::Visible = self.visibility.get(ctx.vars) {
|
||||
if let Visibility::Visible = self.visibility.get(ctx) {
|
||||
self.child.arrange(ctx, final_size)
|
||||
}
|
||||
}
|
||||
|
@ -474,7 +474,7 @@ pub fn visibility(child: impl UiNode, visibility: impl IntoVar<Visibility>) -> i
|
|||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
if let Visibility::Visible = self.visibility.get(ctx.vars) {
|
||||
if let Visibility::Visible = self.visibility.get(ctx) {
|
||||
self.child.render(ctx, frame);
|
||||
} else {
|
||||
frame
|
||||
|
@ -484,7 +484,7 @@ pub fn visibility(child: impl UiNode, visibility: impl IntoVar<Visibility>) -> i
|
|||
}
|
||||
|
||||
fn render_update(&self, ctx: &mut RenderContext, update: &mut FrameUpdate) {
|
||||
if let Visibility::Visible = self.visibility.get(ctx.vars) {
|
||||
if let Visibility::Visible = self.visibility.get(ctx) {
|
||||
self.child.render_update(ctx, update);
|
||||
} else {
|
||||
update.cancel_widget();
|
||||
|
@ -673,7 +673,7 @@ pub fn hit_testable(child: impl UiNode, hit_testable: impl IntoVar<bool>) -> imp
|
|||
#[impl_ui_node(child)]
|
||||
impl<U: UiNode, H: Var<bool>> UiNode for HitTestableNode<U, H> {
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
if !*self.hit_testable.get(ctx.vars) {
|
||||
if !self.hit_testable.copy(ctx) {
|
||||
ctx.widget_state.set::<HitTestableState>(false);
|
||||
}
|
||||
self.with_context(ctx.vars, |c| c.init(ctx));
|
||||
|
@ -684,7 +684,7 @@ pub fn hit_testable(child: impl UiNode, hit_testable: impl IntoVar<bool>) -> imp
|
|||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if let Some(&state) = self.hit_testable.get_new(ctx.vars) {
|
||||
if let Some(&state) = self.hit_testable.get_new(ctx) {
|
||||
ctx.widget_state.set::<HitTestableState>(state);
|
||||
ctx.updates.render();
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ pub fn hit_testable(child: impl UiNode, hit_testable: impl IntoVar<bool>) -> imp
|
|||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
if !self.hit_testable.get(ctx.vars) {
|
||||
if !self.hit_testable.copy(ctx) {
|
||||
frame.push_not_hit_testable(|frame| self.child.render(ctx, frame));
|
||||
} else {
|
||||
self.child.render(ctx, frame);
|
||||
|
|
|
@ -177,7 +177,7 @@ impl HeadlessAppWindowExt for app::HeadlessApp {
|
|||
while window_id.is_none() {
|
||||
self.update_observe(
|
||||
|ctx| {
|
||||
if let Some(opened) = response.response_new(ctx.vars) {
|
||||
if let Some(opened) = response.rsp_new(ctx) {
|
||||
window_id = Some(opened.window_id);
|
||||
}
|
||||
},
|
||||
|
@ -506,7 +506,7 @@ impl AppExtension for WindowManager {
|
|||
// we can determinate if the system only changed the size
|
||||
// to visually match the new scale_factor or if the window was
|
||||
// really resized.
|
||||
if *window.vars.size().get(ctx.vars) == new_size.into() {
|
||||
if window.vars.size().copy(ctx) == new_size.into() {
|
||||
// if it only changed to visually match, the WindowEvent::Resized
|
||||
// will not cause a re-layout, so we need to do it here, but window.resize_renderer()
|
||||
// calls window.size(), so we need to set the new_inner_size before winit.
|
||||
|
@ -613,7 +613,7 @@ impl AppExtension for WindowManager {
|
|||
target: "window",
|
||||
"dropping `{:?} ({})` without closing events",
|
||||
window.id,
|
||||
window.vars.title().get(ctx.vars)
|
||||
window.vars.title().get(ctx)
|
||||
);
|
||||
window.context.borrow_mut().deinit(ctx);
|
||||
}
|
||||
|
@ -2099,22 +2099,22 @@ impl OpenWindow {
|
|||
|
||||
/// Updated inited window.
|
||||
fn update_window(&mut self, ctx: &mut AppContext) {
|
||||
if let Some(title) = self.vars.title().get_new(ctx.vars) {
|
||||
if let Some(title) = self.vars.title().get_new(ctx) {
|
||||
if let Some(window) = &self.window {
|
||||
window.set_title(title);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(icon) = self.vars.icon().get_new(ctx.vars) {
|
||||
if let Some(icon) = self.vars.icon().get_new(ctx) {
|
||||
Self::set_icon(&self.window, icon);
|
||||
}
|
||||
|
||||
if !self.kiosk {
|
||||
if let Some(&auto_size) = self.vars.auto_size().get_new(ctx.vars) {
|
||||
if let Some(auto_size) = self.vars.auto_size().copy_new(ctx) {
|
||||
// size will be updated in self.layout(..)
|
||||
ctx.updates.layout();
|
||||
|
||||
let resizable = auto_size == AutoSize::DISABLED && *self.vars.resizable().get(ctx.vars);
|
||||
let resizable = auto_size == AutoSize::DISABLED && *self.vars.resizable().get(ctx);
|
||||
self.vars.resizable().set_ne(ctx.vars, resizable);
|
||||
|
||||
if let Some(window) = &self.window {
|
||||
|
@ -2122,7 +2122,7 @@ impl OpenWindow {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(&min_size) = self.vars.min_size().get_new(ctx.vars) {
|
||||
if let Some(min_size) = self.vars.min_size().copy_new(ctx) {
|
||||
let factor = self.scale_factor();
|
||||
let prev_min_size = self.min_size;
|
||||
let min_size = ctx.outer_layout_context(self.screen_size(), factor, self.id, self.root_id, |ctx| {
|
||||
|
@ -2148,7 +2148,7 @@ impl OpenWindow {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(&max_size) = self.vars.max_size().get_new(ctx.vars) {
|
||||
if let Some(max_size) = self.vars.max_size().copy_new(ctx) {
|
||||
let factor = self.scale_factor();
|
||||
let prev_max_size = self.max_size;
|
||||
let max_size = ctx.outer_layout_context(self.screen_size(), factor, self.id, self.root_id, |ctx| {
|
||||
|
@ -2174,9 +2174,9 @@ impl OpenWindow {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(&size) = self.vars.size().get_new(ctx.vars) {
|
||||
if let Some(size) = self.vars.size().copy_new(ctx) {
|
||||
let current_size = self.size();
|
||||
if AutoSize::DISABLED == *self.vars.auto_size().get(ctx.vars) {
|
||||
if AutoSize::DISABLED == *self.vars.auto_size().get(ctx) {
|
||||
let factor = self.scale_factor();
|
||||
let mut size = ctx.outer_layout_context(self.screen_size(), factor, self.id, self.root_id, |ctx| {
|
||||
size.to_layout(*ctx.viewport_size, ctx)
|
||||
|
@ -2203,7 +2203,7 @@ impl OpenWindow {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(&pos) = self.vars.position().get_new(ctx.vars) {
|
||||
if let Some(pos) = self.vars.position().copy_new(ctx) {
|
||||
let factor = self.scale_factor();
|
||||
let current_pos = self.position();
|
||||
let mut pos = ctx.outer_layout_context(self.screen_size(), factor, self.id, self.root_id, |ctx| {
|
||||
|
@ -2227,30 +2227,30 @@ impl OpenWindow {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(&always_on_top) = self.vars.always_on_top().get_new(ctx.vars) {
|
||||
if let Some(always_on_top) = self.vars.always_on_top().copy_new(ctx) {
|
||||
if let Some(window) = &self.window {
|
||||
window.set_always_on_top(always_on_top);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(&taskbar_visible) = self.vars.taskbar_visible().get_new(ctx.vars) {
|
||||
if let Some(taskbar_visible) = self.vars.taskbar_visible().copy_new(ctx) {
|
||||
self.set_taskbar_visible(taskbar_visible);
|
||||
}
|
||||
|
||||
if let Some(chrome) = self.vars.chrome().get_new(ctx.vars) {
|
||||
if let Some(chrome) = self.vars.chrome().get_new(ctx) {
|
||||
if let Some(window) = &self.window {
|
||||
window.set_decorations(chrome.is_default());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(&visible) = self.vars.visible().get_new(ctx.vars) {
|
||||
if let Some(visible) = self.vars.visible().copy_new(ctx) {
|
||||
if let Some(window) = &self.window {
|
||||
window.set_visible(visible && matches!(self.init_state, WindowInitState::Inited));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// kiosk mode
|
||||
if let Some(state) = self.vars.state().get_new(ctx.vars) {
|
||||
if let Some(state) = self.vars.state().copy_new(ctx) {
|
||||
match state {
|
||||
WindowState::Normal | WindowState::Minimized | WindowState::Maximized | WindowState::Fullscreen => {
|
||||
self.vars.state().set_ne(ctx.vars, WindowState::Fullscreen);
|
||||
|
@ -2269,31 +2269,31 @@ impl OpenWindow {
|
|||
}
|
||||
}
|
||||
}
|
||||
if self.vars.position().is_new(ctx.vars) {
|
||||
if self.vars.position().is_new(ctx) {
|
||||
self.vars.position().set_ne(ctx.vars, Point::zero());
|
||||
}
|
||||
if self.vars.auto_size().is_new(ctx.vars) {
|
||||
if self.vars.auto_size().is_new(ctx) {
|
||||
self.vars.auto_size().set_ne(ctx.vars, AutoSize::DISABLED);
|
||||
}
|
||||
if self.vars.min_size().is_new(ctx.vars) {
|
||||
if self.vars.min_size().is_new(ctx) {
|
||||
self.vars.min_size().set_ne(ctx.vars, Size::zero());
|
||||
}
|
||||
if self.vars.max_size().is_new(ctx.vars) {
|
||||
if self.vars.max_size().is_new(ctx) {
|
||||
self.vars.max_size().set_ne(ctx.vars, Size::fill());
|
||||
}
|
||||
if self.vars.resizable().is_new(ctx.vars) {
|
||||
if self.vars.resizable().is_new(ctx) {
|
||||
self.vars.resizable().set_ne(ctx.vars, false);
|
||||
}
|
||||
if self.vars.movable().is_new(ctx.vars) {
|
||||
if self.vars.movable().is_new(ctx) {
|
||||
self.vars.movable().set_ne(ctx.vars, false);
|
||||
}
|
||||
if self.vars.always_on_top().is_new(ctx.vars) {
|
||||
if self.vars.always_on_top().is_new(ctx) {
|
||||
self.vars.always_on_top().set_ne(ctx.vars, true);
|
||||
}
|
||||
if self.vars.taskbar_visible().is_new(ctx.vars) {
|
||||
if self.vars.taskbar_visible().is_new(ctx) {
|
||||
self.vars.taskbar_visible().set_ne(ctx.vars, true);
|
||||
}
|
||||
if self.vars.visible().is_new(ctx.vars) {
|
||||
if self.vars.visible().is_new(ctx) {
|
||||
self.vars.visible().set_ne(ctx.vars, true);
|
||||
}
|
||||
}
|
||||
|
@ -2311,7 +2311,7 @@ impl OpenWindow {
|
|||
|
||||
profile_scope!("window::layout");
|
||||
|
||||
let auto_size = *self.vars.auto_size().get(ctx.vars);
|
||||
let auto_size = *self.vars.auto_size().get(ctx);
|
||||
let mut size = self.size();
|
||||
let mut max_size = self.max_size;
|
||||
if auto_size.contains(AutoSize::CONTENT_WIDTH) {
|
||||
|
@ -2361,7 +2361,7 @@ impl OpenWindow {
|
|||
StartPosition::Default => None,
|
||||
StartPosition::CenterScreen => Some(LayoutRect::from_size(self.screen_size())),
|
||||
StartPosition::CenterParent => {
|
||||
if let Some(parent_id) = self.vars.parent().get(ctx.vars) {
|
||||
if let Some(parent_id) = self.vars.parent().get(ctx) {
|
||||
if let Ok(parent) = ctx.services.windows().window(*parent_id) {
|
||||
Some(LayoutRect::new(parent.position(), parent.size()))
|
||||
} else {
|
||||
|
|
|
@ -260,7 +260,7 @@ pub mod core {
|
|||
/// impl<C: UiNode, V: Var<&'static str>> UiNode for MyNode<C, V> {
|
||||
/// fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
/// self.child.init(ctx);
|
||||
/// println!("{}", self.value.get(ctx.vars));
|
||||
/// println!("{}", self.value.get(ctx));
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
@ -1014,7 +1014,7 @@ pub mod prelude {
|
|||
/// impl<C: UiNode, V: Var<bool>> UiNode for MyPropertyNode<C, V> {
|
||||
/// fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
/// self.child.update(ctx);
|
||||
/// if let Some(new_value) = self.value.get_new(ctx.vars) {
|
||||
/// if let Some(new_value) = self.value.get_new(ctx) {
|
||||
/// todo!()
|
||||
/// }
|
||||
/// }
|
||||
|
|
|
@ -38,18 +38,18 @@ pub fn border(
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
|
||||
if self.widths.is_new(ctx.vars) || self.radius.is_new(ctx.vars) {
|
||||
if self.widths.is_new(ctx) || self.radius.is_new(ctx) {
|
||||
ctx.updates.layout()
|
||||
}
|
||||
if self.sides.is_new(ctx.vars) {
|
||||
if self.sides.is_new(ctx) {
|
||||
ctx.updates.render()
|
||||
}
|
||||
}
|
||||
|
||||
#[UiNode]
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
self.final_widths = self.widths.get(ctx.vars).to_layout(available_size, ctx);
|
||||
self.final_radius = self.radius.get(ctx.vars).to_layout(available_size, ctx);
|
||||
self.final_widths = self.widths.get(ctx).to_layout(available_size, ctx);
|
||||
self.final_radius = self.radius.get(ctx).to_layout(available_size, ctx);
|
||||
|
||||
let size_inc = self.size_increment();
|
||||
self.child.measure(ctx, available_size - size_inc) + size_inc
|
||||
|
@ -73,7 +73,7 @@ pub fn border(
|
|||
frame.push_border(
|
||||
LayoutRect::from_size(self.final_size),
|
||||
self.final_widths,
|
||||
*self.sides.get(ctx.vars),
|
||||
*self.sides.get(ctx),
|
||||
self.final_radius,
|
||||
);
|
||||
frame.push_reference_frame(self.child_rect.origin, |frame| self.child.render(ctx, frame));
|
||||
|
|
|
@ -35,11 +35,11 @@ pub fn capture_mouse(child: impl UiNode, mode: impl IntoVar<CaptureMode>) -> imp
|
|||
impl<C: UiNode, M: Var<CaptureMode>> UiNode for CaptureMouseNode<C, M> {
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = MouseDownEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
let mouse = ctx.services.mouse();
|
||||
let widget_id = ctx.path.widget_id();
|
||||
|
||||
match *self.mode.get(ctx.vars) {
|
||||
match self.mode.copy(ctx.vars) {
|
||||
CaptureMode::Widget => {
|
||||
mouse.capture_widget(widget_id);
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ pub fn capture_mouse(child: impl UiNode, mode: impl IntoVar<CaptureMode>) -> imp
|
|||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if let Some(&new_mode) = self.mode.get_new(ctx.vars) {
|
||||
if IsEnabled::get(ctx.vars) {
|
||||
if let Some(new_mode) = self.mode.copy_new(ctx) {
|
||||
if IsEnabled::get(ctx) {
|
||||
let mouse = ctx.services.mouse();
|
||||
let widget_id = ctx.path.widget_id();
|
||||
if let Some((current, _)) = mouse.current_capture() {
|
||||
|
|
|
@ -21,14 +21,14 @@ pub fn cursor(child: impl UiNode, cursor: impl IntoVar<CursorIcon>) -> impl UiNo
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, C: Var<CursorIcon>> UiNode for CursorNode<T, C> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.cursor.is_new(&ctx.vars) {
|
||||
if self.cursor.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
frame.push_cursor(*self.cursor.get(ctx.vars), |frame| self.child.render(ctx, frame));
|
||||
frame.push_cursor(self.cursor.copy(ctx), |frame| self.child.render(ctx, frame));
|
||||
}
|
||||
}
|
||||
CursorNode {
|
||||
|
|
|
@ -15,7 +15,7 @@ pub fn draggable(child: impl UiNode, enabled: impl IntoVar<bool>) -> impl UiNode
|
|||
impl<C: UiNode, E: Var<bool>> UiNode for DraggableNode<C, E> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
if *self.enabled.get(ctx.vars) {
|
||||
if self.enabled.copy(ctx) {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ where
|
|||
{
|
||||
if let Some(args) = ShortcutEvent.update(args) {
|
||||
self.child.event(ctx, args);
|
||||
if !args.stop_propagation_requested() && self.shortcuts.get(ctx.vars).0.contains(&args.shortcut) {
|
||||
if !args.stop_propagation_requested() && self.shortcuts.get(ctx).0.contains(&args.shortcut) {
|
||||
// this request also focus the widget if the window is focused
|
||||
// and the widget is focusable.
|
||||
ctx.services
|
||||
|
|
|
@ -21,14 +21,14 @@ pub fn filter(child: impl UiNode, filter: impl IntoVar<Filter>) -> impl UiNode {
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, F: Var<Filter>> UiNode for FilterNode<C, F> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.filter.is_new(ctx.vars) {
|
||||
if self.filter.is_new(ctx) {
|
||||
ctx.updates.layout() //TODO don't use layout when not needed.
|
||||
}
|
||||
self.child.update(ctx)
|
||||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.render_filter = self.filter.get(ctx.vars).to_render(final_size, ctx);
|
||||
self.render_filter = self.filter.get(ctx).to_render(final_size, ctx);
|
||||
self.child.arrange(ctx, final_size);
|
||||
}
|
||||
|
||||
|
@ -115,14 +115,14 @@ pub fn opacity(child: impl UiNode, alpha: impl IntoVar<FactorNormal>) -> impl Ui
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, A: Var<FactorNormal>> UiNode for OpacityNode<C, A> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.alpha_value.is_new(ctx.vars) {
|
||||
if self.alpha_value.is_new(ctx) {
|
||||
ctx.updates.render_update();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
let opacity = self.alpha_value.get(ctx.vars).0;
|
||||
let opacity = self.alpha_value.get(ctx).0;
|
||||
let opacity = if let Some(frame_key) = self.frame_key {
|
||||
frame_key.bind(opacity)
|
||||
} else {
|
||||
|
@ -133,7 +133,7 @@ pub fn opacity(child: impl UiNode, alpha: impl IntoVar<FactorNormal>) -> impl Ui
|
|||
|
||||
fn render_update(&self, ctx: &mut RenderContext, update: &mut FrameUpdate) {
|
||||
if let Some(frame_key) = self.frame_key {
|
||||
update.update_f32(frame_key.update(self.alpha_value.get(ctx.vars).0));
|
||||
update.update_f32(frame_key.update(self.alpha_value.get(ctx).0));
|
||||
}
|
||||
self.child.render_update(ctx, update);
|
||||
}
|
||||
|
|
|
@ -14,14 +14,14 @@ pub fn focusable(child: impl UiNode, focusable: impl IntoVar<bool>) -> impl UiNo
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, E: Var<bool>> UiNode for FocusableNode<C, E> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.is_focusable.is_new(ctx.vars) {
|
||||
if self.is_focusable.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().focusable = Some(*self.is_focusable.get(ctx.vars));
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().focusable = Some(*self.is_focusable.get(ctx));
|
||||
self.child.render(ctx, frame);
|
||||
}
|
||||
}
|
||||
|
@ -45,14 +45,14 @@ pub fn tab_index(child: impl UiNode, tab_index: impl IntoVar<TabIndex>) -> impl
|
|||
T: Var<TabIndex>,
|
||||
{
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.tab_index.is_new(ctx.vars) {
|
||||
if self.tab_index.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().tab_index = Some(*self.tab_index.get(ctx.vars));
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().tab_index = Some(*self.tab_index.get(ctx));
|
||||
self.child.render(ctx, frame);
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ struct FocusScopeNode<C: UiNode, E: Var<bool>> {
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, E: Var<bool>> UiNode for FocusScopeNode<C, E> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.is_focus_scope.is_new(ctx.vars) {
|
||||
if self.is_focus_scope.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
|
@ -98,7 +98,7 @@ impl<C: UiNode, E: Var<bool>> UiNode for FocusScopeNode<C, E> {
|
|||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
let info = frame.meta().entry::<FocusInfoKey>().or_default();
|
||||
info.scope = Some(*self.is_focus_scope.get(ctx.vars));
|
||||
info.scope = Some(self.is_focus_scope.copy(ctx));
|
||||
if self.is_alt {
|
||||
info.alt_scope = true;
|
||||
|
||||
|
@ -129,7 +129,7 @@ pub fn focus_scope_behavior(child: impl UiNode, behavior: impl IntoVar<FocusScop
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, B: Var<FocusScopeOnFocus>> UiNode for FocusScopeBehaviorNode<C, B> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.behavior.is_new(ctx.vars) {
|
||||
if self.behavior.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
|
@ -137,7 +137,7 @@ pub fn focus_scope_behavior(child: impl UiNode, behavior: impl IntoVar<FocusScop
|
|||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
let info = frame.meta().entry::<FocusInfoKey>().or_default();
|
||||
info.on_focus = *self.behavior.get(ctx.vars);
|
||||
info.on_focus = self.behavior.copy(ctx);
|
||||
if info.scope.is_none() {
|
||||
info.scope = Some(true);
|
||||
}
|
||||
|
@ -160,14 +160,14 @@ pub fn tab_nav(child: impl UiNode, tab_nav: impl IntoVar<TabNav>) -> impl UiNode
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, E: Var<TabNav>> UiNode for TabNavNode<C, E> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.tab_nav.is_new(ctx.vars) {
|
||||
if self.tab_nav.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().tab_nav = Some(*self.tab_nav.get(ctx.vars));
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().tab_nav = Some(self.tab_nav.copy(ctx));
|
||||
self.child.render(ctx, frame);
|
||||
}
|
||||
}
|
||||
|
@ -187,14 +187,14 @@ pub fn directional_nav(child: impl UiNode, directional_nav: impl IntoVar<Directi
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, E: Var<DirectionalNav>> UiNode for DirectionalNavNode<C, E> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.directional_nav.is_new(ctx.vars) {
|
||||
if self.directional_nav.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().directional_nav = Some(*self.directional_nav.get(ctx.vars));
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().directional_nav = Some(self.directional_nav.copy(ctx));
|
||||
self.child.render(ctx, frame);
|
||||
}
|
||||
}
|
||||
|
@ -219,7 +219,7 @@ pub fn focus_shortcut(child: impl UiNode, shortcuts: impl IntoVar<Shortcuts>) ->
|
|||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = ShortcutEvent.update(args) {
|
||||
self.child.event(ctx, args);
|
||||
if !args.stop_propagation_requested() && self.shortcuts.get(ctx.vars).0.contains(&args.shortcut) {
|
||||
if !args.stop_propagation_requested() && self.shortcuts.get(ctx).0.contains(&args.shortcut) {
|
||||
// focus on shortcut
|
||||
ctx.services.focus().focus_widget_or_related(ctx.path.widget_id(), true);
|
||||
args.stop_propagation();
|
||||
|
@ -251,14 +251,14 @@ pub fn skip_directional(child: impl UiNode, enabled: impl IntoVar<bool>) -> impl
|
|||
E: Var<bool>,
|
||||
{
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.enabled.is_new(ctx.vars) {
|
||||
if self.enabled.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().skip_directional = Some(*self.enabled.get(ctx.vars));
|
||||
frame.meta().entry::<FocusInfoKey>().or_default().skip_directional = Some(self.enabled.copy(ctx));
|
||||
self.child.render(ctx, frame);
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ pub fn is_focused(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = FocusChangedEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) {
|
||||
if IsEnabled::get(ctx) {
|
||||
self.is_focused = args
|
||||
.new_focus
|
||||
.as_ref()
|
||||
|
@ -345,7 +345,7 @@ pub fn is_focused(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_focused = false;
|
||||
}
|
||||
|
||||
|
@ -379,7 +379,7 @@ pub fn is_focus_within(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = FocusChangedEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) {
|
||||
if IsEnabled::get(ctx) {
|
||||
self.is_focus_within = args
|
||||
.new_focus
|
||||
.as_ref()
|
||||
|
@ -395,7 +395,7 @@ pub fn is_focus_within(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_focus_within = false;
|
||||
}
|
||||
self.state.set_ne(ctx.vars, self.is_focus_within);
|
||||
|
@ -431,7 +431,7 @@ pub fn is_focused_hgl(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = FocusChangedEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) {
|
||||
if IsEnabled::get(ctx) {
|
||||
self.is_focused_hgl = args.highlight
|
||||
&& args
|
||||
.new_focus
|
||||
|
@ -449,7 +449,7 @@ pub fn is_focused_hgl(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_focused_hgl = false;
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,7 @@ pub fn is_focus_within_hgl(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = FocusChangedEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) {
|
||||
if IsEnabled::get(ctx) {
|
||||
self.is_focus_within_hgl = args.highlight
|
||||
&& args
|
||||
.new_focus
|
||||
|
@ -504,7 +504,7 @@ pub fn is_focus_within_hgl(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_focus_within_hgl = false;
|
||||
}
|
||||
|
||||
|
@ -536,7 +536,7 @@ pub fn is_return_focus(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = ReturnFocusChangedEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) {
|
||||
if IsEnabled::get(ctx) {
|
||||
if args
|
||||
.prev_return
|
||||
.as_ref()
|
||||
|
@ -562,7 +562,7 @@ pub fn is_return_focus(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_return_focus = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,14 +44,14 @@ pub fn margin(child: impl UiNode, margin: impl IntoVar<SideOffsets>) -> impl UiN
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, M: Var<SideOffsets>> UiNode for MarginNode<T, M> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.margin.is_new(ctx.vars) {
|
||||
if self.margin.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
let margin = self.margin.get(ctx.vars).to_layout(available_size, ctx);
|
||||
let margin = self.margin.get(ctx).to_layout(available_size, ctx);
|
||||
self.size_increment = LayoutSize::new(margin.left + margin.right, margin.top + margin.bottom);
|
||||
self.child_rect.origin = LayoutPoint::new(margin.left, margin.top);
|
||||
self.child.measure(ctx, available_size - self.size_increment) + self.size_increment
|
||||
|
@ -103,7 +103,7 @@ pub fn align(child: impl UiNode, alignment: impl IntoVar<Alignment>) -> impl UiN
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, A: Var<Alignment>> UiNode for AlignNode<T, A> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.alignment.is_new(ctx.vars) {
|
||||
if self.alignment.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ pub fn align(child: impl UiNode, alignment: impl IntoVar<Alignment>) -> impl UiN
|
|||
self.child_rect.size = final_size.min(self.child_rect.size);
|
||||
self.child.arrange(ctx, self.child_rect.size);
|
||||
|
||||
let alignment = self.alignment.get(ctx.vars);
|
||||
let alignment = self.alignment.get(ctx);
|
||||
|
||||
self.child_rect.origin = LayoutPoint::new(
|
||||
(final_size.width - self.child_rect.size.width) * alignment.x.0,
|
||||
|
@ -172,7 +172,7 @@ pub fn position(child: impl UiNode, position: impl IntoVar<Point>) -> impl UiNod
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, P: Var<Point>> UiNode for PositionNode<T, P> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.position.is_new(ctx.vars) {
|
||||
if self.position.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
|
@ -180,7 +180,7 @@ pub fn position(child: impl UiNode, position: impl IntoVar<Point>) -> impl UiNod
|
|||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.child.arrange(ctx, final_size);
|
||||
self.final_position = self.position.get(ctx.vars).to_layout(final_size, ctx);
|
||||
self.final_position = self.position.get(ctx).to_layout(final_size, ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
|
@ -225,7 +225,7 @@ pub fn x(child: impl UiNode, x: impl IntoVar<Length>) -> impl UiNode {
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, X: Var<Length>> UiNode for XNode<T, X> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.x.is_new(ctx.vars) {
|
||||
if self.x.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
|
@ -233,7 +233,7 @@ pub fn x(child: impl UiNode, x: impl IntoVar<Length>) -> impl UiNode {
|
|||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.child.arrange(ctx, final_size);
|
||||
self.final_x = self.x.get(ctx.vars).to_layout(LayoutLength::new(final_size.width), ctx);
|
||||
self.final_x = self.x.get(ctx).to_layout(LayoutLength::new(final_size.width), ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
|
@ -278,7 +278,7 @@ pub fn y(child: impl UiNode, y: impl IntoVar<Length>) -> impl UiNode {
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, Y: Var<Length>> UiNode for YNode<T, Y> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.y.is_new(ctx.vars) {
|
||||
if self.y.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
|
@ -286,7 +286,7 @@ pub fn y(child: impl UiNode, y: impl IntoVar<Length>) -> impl UiNode {
|
|||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.child.arrange(ctx, final_size);
|
||||
self.final_y = self.y.get(ctx.vars).to_layout(LayoutLength::new(final_size.height), ctx);
|
||||
self.final_y = self.y.get(ctx).to_layout(LayoutLength::new(final_size.height), ctx);
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
|
@ -333,7 +333,7 @@ pub fn min_size(child: impl UiNode, min_size: impl IntoVar<Size>) -> impl UiNode
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, S: Var<Size>> UiNode for MinSizeNode<T, S> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.min_size.is_new(ctx.vars) {
|
||||
if self.min_size.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -341,7 +341,7 @@ pub fn min_size(child: impl UiNode, min_size: impl IntoVar<Size>) -> impl UiNode
|
|||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
let min_size = self.min_size.get(ctx.vars).to_layout(available_size, ctx);
|
||||
let min_size = self.min_size.get(ctx).to_layout(available_size, ctx);
|
||||
let desired_size = self
|
||||
.child
|
||||
.measure(ctx, replace_layout_any_size(min_size, available_size).max(available_size));
|
||||
|
@ -349,7 +349,7 @@ pub fn min_size(child: impl UiNode, min_size: impl IntoVar<Size>) -> impl UiNode
|
|||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
let min_size = replace_layout_any_size(self.min_size.get(ctx.vars).to_layout(final_size, ctx), final_size);
|
||||
let min_size = replace_layout_any_size(self.min_size.get(ctx).to_layout(final_size, ctx), final_size);
|
||||
self.child.arrange(ctx, min_size.max(final_size));
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ pub fn min_width(child: impl UiNode, min_width: impl IntoVar<Length>) -> impl Ui
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, W: Var<Length>> UiNode for MinWidthNode<T, W> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.min_width.is_new(ctx.vars) {
|
||||
if self.min_width.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -401,7 +401,7 @@ pub fn min_width(child: impl UiNode, min_width: impl IntoVar<Length>) -> impl Ui
|
|||
fn measure(&mut self, ctx: &mut LayoutContext, mut available_size: LayoutSize) -> LayoutSize {
|
||||
let min_width = self
|
||||
.min_width
|
||||
.get(ctx.vars)
|
||||
.get(ctx)
|
||||
.to_layout(LayoutLength::new(available_size.width), ctx)
|
||||
.get();
|
||||
|
||||
|
@ -416,11 +416,7 @@ pub fn min_width(child: impl UiNode, min_width: impl IntoVar<Length>) -> impl Ui
|
|||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, mut final_size: LayoutSize) {
|
||||
let min_width = self
|
||||
.min_width
|
||||
.get(ctx.vars)
|
||||
.to_layout(LayoutLength::new(final_size.width), ctx)
|
||||
.get();
|
||||
let min_width = self.min_width.get(ctx).to_layout(LayoutLength::new(final_size.width), ctx).get();
|
||||
if !is_layout_any_size(min_width) {
|
||||
final_size.width = min_width.max(final_size.width);
|
||||
}
|
||||
|
@ -465,7 +461,7 @@ pub fn min_height(child: impl UiNode, min_height: impl IntoVar<Length>) -> impl
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, H: Var<Length>> UiNode for MinHeightNode<T, H> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.min_height.is_new(ctx.vars) {
|
||||
if self.min_height.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -475,7 +471,7 @@ pub fn min_height(child: impl UiNode, min_height: impl IntoVar<Length>) -> impl
|
|||
fn measure(&mut self, ctx: &mut LayoutContext, mut available_size: LayoutSize) -> LayoutSize {
|
||||
let min_height = self
|
||||
.min_height
|
||||
.get(ctx.vars)
|
||||
.get(ctx)
|
||||
.to_layout(LayoutLength::new(available_size.height), ctx)
|
||||
.get();
|
||||
if !is_layout_any_size(min_height) {
|
||||
|
@ -489,11 +485,7 @@ pub fn min_height(child: impl UiNode, min_height: impl IntoVar<Length>) -> impl
|
|||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, mut final_size: LayoutSize) {
|
||||
let min_height = self
|
||||
.min_height
|
||||
.get(ctx.vars)
|
||||
.to_layout(LayoutLength::new(final_size.height), ctx)
|
||||
.get();
|
||||
let min_height = self.min_height.get(ctx).to_layout(LayoutLength::new(final_size.height), ctx).get();
|
||||
if !is_layout_any_size(min_height) {
|
||||
final_size.height = min_height.max(final_size.height);
|
||||
}
|
||||
|
@ -539,7 +531,7 @@ pub fn max_size(child: impl UiNode, max_size: impl IntoVar<Size>) -> impl UiNode
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, S: Var<Size>> UiNode for MaxSizeNode<T, S> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.max_size.is_new(ctx.vars) {
|
||||
if self.max_size.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -547,13 +539,13 @@ pub fn max_size(child: impl UiNode, max_size: impl IntoVar<Size>) -> impl UiNode
|
|||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
let max_size = self.max_size.get(ctx.vars).to_layout(available_size, ctx);
|
||||
let max_size = self.max_size.get(ctx).to_layout(available_size, ctx);
|
||||
self.child.measure(ctx, max_size.min(available_size)).min(max_size)
|
||||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.child
|
||||
.arrange(ctx, self.max_size.get(ctx.vars).to_layout(final_size, ctx).min(final_size));
|
||||
.arrange(ctx, self.max_size.get(ctx).to_layout(final_size, ctx).min(final_size));
|
||||
}
|
||||
}
|
||||
MaxSizeNode {
|
||||
|
@ -594,7 +586,7 @@ pub fn max_width(child: impl UiNode, max_width: impl IntoVar<Length>) -> impl Ui
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, W: Var<Length>> UiNode for MaxWidthNode<T, W> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.max_width.is_new(ctx.vars) {
|
||||
if self.max_width.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -604,7 +596,7 @@ pub fn max_width(child: impl UiNode, max_width: impl IntoVar<Length>) -> impl Ui
|
|||
fn measure(&mut self, ctx: &mut LayoutContext, mut available_size: LayoutSize) -> LayoutSize {
|
||||
let max_width = self
|
||||
.max_width
|
||||
.get(ctx.vars)
|
||||
.get(ctx)
|
||||
.to_layout(LayoutLength::new(available_size.width), ctx)
|
||||
.get();
|
||||
|
||||
|
@ -620,7 +612,7 @@ pub fn max_width(child: impl UiNode, max_width: impl IntoVar<Length>) -> impl Ui
|
|||
fn arrange(&mut self, ctx: &mut LayoutContext, mut final_size: LayoutSize) {
|
||||
final_size.width = self
|
||||
.max_width
|
||||
.get(ctx.vars)
|
||||
.get(ctx)
|
||||
.to_layout(LayoutLength::new(final_size.width), ctx)
|
||||
.get()
|
||||
.min(final_size.width);
|
||||
|
@ -665,7 +657,7 @@ pub fn max_height(child: impl UiNode, max_height: impl IntoVar<Length>) -> impl
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, H: Var<Length>> UiNode for MaxHeightNode<T, H> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.max_height.is_new(ctx.vars) {
|
||||
if self.max_height.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -675,7 +667,7 @@ pub fn max_height(child: impl UiNode, max_height: impl IntoVar<Length>) -> impl
|
|||
fn measure(&mut self, ctx: &mut LayoutContext, mut available_size: LayoutSize) -> LayoutSize {
|
||||
let max_height = self
|
||||
.max_height
|
||||
.get(ctx.vars)
|
||||
.get(ctx)
|
||||
.to_layout(LayoutLength::new(available_size.height), ctx)
|
||||
.get();
|
||||
|
||||
|
@ -691,7 +683,7 @@ pub fn max_height(child: impl UiNode, max_height: impl IntoVar<Length>) -> impl
|
|||
fn arrange(&mut self, ctx: &mut LayoutContext, mut final_size: LayoutSize) {
|
||||
final_size.height = self
|
||||
.max_height
|
||||
.get(ctx.vars)
|
||||
.get(ctx)
|
||||
.to_layout(LayoutLength::new(final_size.height), ctx)
|
||||
.get()
|
||||
.min(final_size.height);
|
||||
|
@ -736,7 +728,7 @@ pub fn size(child: impl UiNode, size: impl IntoVar<Size>) -> impl UiNode {
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, S: Var<Size>> UiNode for SizeNode<T, S> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.size.is_new(ctx.vars) {
|
||||
if self.size.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -744,13 +736,13 @@ pub fn size(child: impl UiNode, size: impl IntoVar<Size>) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
let size = self.size.get(ctx.vars).to_layout(available_size, ctx);
|
||||
let size = self.size.get(ctx).to_layout(available_size, ctx);
|
||||
let desired_size = self.child.measure(ctx, replace_layout_any_size(size, available_size));
|
||||
replace_layout_any_size(size, desired_size)
|
||||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
let size = replace_layout_any_size(self.size.get(ctx.vars).to_layout(final_size, ctx), final_size);
|
||||
let size = replace_layout_any_size(self.size.get(ctx).to_layout(final_size, ctx), final_size);
|
||||
self.child.arrange(ctx, size);
|
||||
}
|
||||
}
|
||||
|
@ -788,7 +780,7 @@ pub fn width(child: impl UiNode, width: impl IntoVar<Length>) -> impl UiNode {
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, W: Var<Length>> UiNode for WidthNode<T, W> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.width.is_new(ctx.vars) {
|
||||
if self.width.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -796,11 +788,7 @@ pub fn width(child: impl UiNode, width: impl IntoVar<Length>) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, mut available_size: LayoutSize) -> LayoutSize {
|
||||
let width = self
|
||||
.width
|
||||
.get(ctx.vars)
|
||||
.to_layout(LayoutLength::new(available_size.width), ctx)
|
||||
.get();
|
||||
let width = self.width.get(ctx).to_layout(LayoutLength::new(available_size.width), ctx).get();
|
||||
if !is_layout_any_size(width) {
|
||||
available_size.width = width;
|
||||
let mut desired_size = self.child.measure(ctx, available_size);
|
||||
|
@ -812,7 +800,7 @@ pub fn width(child: impl UiNode, width: impl IntoVar<Length>) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, mut final_size: LayoutSize) {
|
||||
let width = self.width.get(ctx.vars).to_layout(LayoutLength::new(final_size.width), ctx).get();
|
||||
let width = self.width.get(ctx).to_layout(LayoutLength::new(final_size.width), ctx).get();
|
||||
if !is_layout_any_size(width) {
|
||||
final_size.width = width;
|
||||
}
|
||||
|
@ -853,7 +841,7 @@ pub fn height(child: impl UiNode, height: impl IntoVar<Length>) -> impl UiNode {
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, H: Var<Length>> UiNode for HeightNode<T, H> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.height.is_new(ctx.vars) {
|
||||
if self.height.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
|
||||
|
@ -861,11 +849,7 @@ pub fn height(child: impl UiNode, height: impl IntoVar<Length>) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, mut available_size: LayoutSize) -> LayoutSize {
|
||||
let height = self
|
||||
.height
|
||||
.get(ctx.vars)
|
||||
.to_layout(LayoutLength::new(available_size.height), ctx)
|
||||
.get();
|
||||
let height = self.height.get(ctx).to_layout(LayoutLength::new(available_size.height), ctx).get();
|
||||
if !is_layout_any_size(height) {
|
||||
available_size.height = height;
|
||||
let mut desired_size = self.child.measure(ctx, available_size);
|
||||
|
@ -877,7 +861,7 @@ pub fn height(child: impl UiNode, height: impl IntoVar<Length>) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, mut final_size: LayoutSize) {
|
||||
let height = self.height.get(ctx.vars).to_layout(LayoutLength::new(final_size.height), ctx).get();
|
||||
let height = self.height.get(ctx).to_layout(LayoutLength::new(final_size.height), ctx).get();
|
||||
if !is_layout_any_size(height) {
|
||||
final_size.height = height;
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ pub fn is_hovered(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = MouseEnterEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_hovered = true;
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = MouseLeaveEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_hovered = false;
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
|
@ -48,7 +48,7 @@ pub fn is_hovered(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_hovered = false;
|
||||
}
|
||||
self.state.set_ne(ctx.vars, self.is_hovered);
|
||||
|
@ -84,17 +84,17 @@ pub fn is_cap_hovered(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = MouseEnterEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_hovered = true;
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = MouseLeaveEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_hovered = false;
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = MouseCaptureEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
if args.is_got(ctx.path.widget_id()) {
|
||||
self.is_captured = true;
|
||||
} else if args.is_lost(ctx.path.widget_id()) {
|
||||
|
@ -108,7 +108,7 @@ pub fn is_cap_hovered(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_hovered = false;
|
||||
self.is_captured = false;
|
||||
}
|
||||
|
@ -157,17 +157,17 @@ pub fn is_pressed(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = MouseEnterEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_over = true;
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = MouseLeaveEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_over = false;
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = MouseInputEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.is_primary() {
|
||||
if IsEnabled::get(ctx) && args.is_primary() {
|
||||
match args.state {
|
||||
ElementState::Pressed => {
|
||||
if args.concerns_capture(ctx) {
|
||||
|
@ -180,7 +180,7 @@ pub fn is_pressed(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
}
|
||||
}
|
||||
} else if let Some(args) = ClickEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) && args.shortcut().is_some() {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) && args.shortcut().is_some() {
|
||||
// if a shortcut click happened, we show pressed for the duration of `shortcut_press`
|
||||
// unless we where already doing that, then we just stop showing pressed, this causes
|
||||
// a flickering effect when rapid clicks are happening.
|
||||
|
@ -193,7 +193,7 @@ pub fn is_pressed(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = WindowBlurEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_down = false;
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
|
@ -205,12 +205,12 @@ pub fn is_pressed(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_down = false;
|
||||
self.is_over = false;
|
||||
self.shortcut_press = None;
|
||||
} else if let Some(timer) = &self.shortcut_press {
|
||||
if timer.is_new(ctx.vars) {
|
||||
if timer.is_new(ctx) {
|
||||
self.shortcut_press = None;
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ pub fn is_cap_pressed(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
|
||||
fn event<EU: EventUpdateArgs>(&mut self, ctx: &mut WidgetContext, args: &EU) {
|
||||
if let Some(args) = MouseInputEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.is_primary() {
|
||||
if IsEnabled::get(ctx) && args.is_primary() {
|
||||
match args.state {
|
||||
ElementState::Pressed => {
|
||||
if args.concerns_capture(ctx) {
|
||||
|
@ -266,17 +266,17 @@ pub fn is_cap_pressed(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = MouseCaptureEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_captured = args.is_got(ctx.path.widget_id());
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = WindowBlurEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) {
|
||||
self.is_down = false;
|
||||
}
|
||||
self.child.event(ctx, args);
|
||||
} else if let Some(args) = ClickEvent.update(args) {
|
||||
if IsEnabled::get(ctx.vars) && args.concerns_widget(ctx) && args.shortcut().is_some() {
|
||||
if IsEnabled::get(ctx) && args.concerns_widget(ctx) && args.shortcut().is_some() {
|
||||
// see `is_pressed` for details of what is happening here.
|
||||
if self.shortcut_press.take().is_none() {
|
||||
let duration = ctx.services.gestures().shortcut_pressed_duration;
|
||||
|
@ -294,12 +294,12 @@ pub fn is_cap_pressed(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
|
||||
if let Some(false) = IsEnabled::get_new(ctx.vars) {
|
||||
if let Some(false) = IsEnabled::get_new(ctx) {
|
||||
self.is_down = false;
|
||||
self.is_captured = false;
|
||||
self.shortcut_press = None;
|
||||
} else if let Some(timer) = &self.shortcut_press {
|
||||
if timer.is_new(ctx.vars) {
|
||||
if timer.is_new(ctx) {
|
||||
self.shortcut_press = None;
|
||||
}
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ pub fn is_hit_testable(child: impl UiNode, state: StateVar) -> impl UiNode {
|
|||
}
|
||||
impl<C: UiNode> IsHitTestableNode<C> {
|
||||
fn update_state(&self, ctx: &mut WidgetContext) {
|
||||
let hit_testable = IsHitTestable::get(ctx.vars) && ctx.widget_state.hit_testable();
|
||||
let hit_testable = IsHitTestable::get(ctx) && ctx.widget_state.hit_testable();
|
||||
self.state.set_ne(ctx.vars, hit_testable);
|
||||
}
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ struct IsEnabledNode<C: UiNode> {
|
|||
}
|
||||
impl<C: UiNode> IsEnabledNode<C> {
|
||||
fn update_state(&self, ctx: &mut WidgetContext) {
|
||||
let enabled = IsEnabled::get(ctx.vars) && ctx.widget_state.enabled();
|
||||
let enabled = IsEnabled::get(ctx) && ctx.widget_state.enabled();
|
||||
let is_state = enabled == self.expected;
|
||||
self.state.set_ne(ctx.vars, is_state);
|
||||
}
|
||||
|
@ -407,7 +407,7 @@ struct IsVisibilityNode<C: UiNode> {
|
|||
}
|
||||
impl<C: UiNode> IsVisibilityNode<C> {
|
||||
fn update_state(&self, ctx: &mut WidgetContext) {
|
||||
let vis = VisibilityContext::get(ctx.vars) | ctx.widget_state.visibility();
|
||||
let vis = VisibilityContext::get(ctx) | ctx.widget_state.visibility();
|
||||
let is_state = vis == self.expected;
|
||||
self.state.set_ne(ctx.vars, is_state);
|
||||
}
|
||||
|
|
|
@ -202,11 +202,11 @@ pub fn with_font_variation(child: impl UiNode, name: FontVariationName, value: i
|
|||
V: Var<f32>,
|
||||
{
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
self.variations = FontVariationsVar::get(ctx.vars).clone();
|
||||
self.variations.insert(self.name, *self.value.get(ctx.vars));
|
||||
self.variations = FontVariationsVar::get(ctx).clone();
|
||||
self.variations.insert(self.name, self.value.copy(ctx));
|
||||
|
||||
self.version = FontVariationsVar::version(ctx.vars);
|
||||
let is_new = FontVariationsVar::is_new(ctx.vars);
|
||||
self.version = FontVariationsVar::version(ctx);
|
||||
let is_new = FontVariationsVar::is_new(ctx);
|
||||
|
||||
if is_new {
|
||||
self.version = self.version.wrapping_add(1);
|
||||
|
@ -230,12 +230,12 @@ pub fn with_font_variation(child: impl UiNode, name: FontVariationName, value: i
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
let mut is_new = false;
|
||||
|
||||
if let Some(new_ctx) = FontVariationsVar::get_new(ctx.vars) {
|
||||
if let Some(new_ctx) = FontVariationsVar::get_new(ctx) {
|
||||
self.variations = new_ctx.clone();
|
||||
self.variations.insert(self.name, *self.value.get(ctx.vars));
|
||||
self.variations.insert(self.name, self.value.copy(ctx));
|
||||
self.version = self.version.wrapping_add(1);
|
||||
is_new = true;
|
||||
} else if let Some(value) = self.value.get_new(ctx.vars) {
|
||||
} else if let Some(value) = self.value.copy(ctx) {
|
||||
self.variations.insert(self.name, *value);
|
||||
self.version = self.version.wrapping_add(1);
|
||||
is_new = true;
|
||||
|
@ -327,14 +327,14 @@ where
|
|||
D: FnMut(&mut FontFeatures, S) -> S + 'static,
|
||||
{
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
self.features = FontFeaturesVar::get(ctx.vars).clone();
|
||||
self.version = FontFeaturesVar::version(ctx.vars);
|
||||
let is_new = FontFeaturesVar::is_new(ctx.vars);
|
||||
self.features = FontFeaturesVar::get(ctx).clone();
|
||||
self.version = FontFeaturesVar::version(ctx);
|
||||
let is_new = FontFeaturesVar::is_new(ctx);
|
||||
if is_new {
|
||||
self.version = self.version.wrapping_add(1);
|
||||
}
|
||||
|
||||
(self.set_feature)(&mut self.features, self.var.get(ctx.vars).clone());
|
||||
(self.set_feature)(&mut self.features, self.var.get_clone(ctx));
|
||||
|
||||
let child = &mut self.child;
|
||||
ctx.vars
|
||||
|
@ -353,12 +353,12 @@ where
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
let mut is_new = false;
|
||||
|
||||
if let Some(new_ctx) = FontFeaturesVar::get_new(ctx.vars) {
|
||||
if let Some(new_ctx) = FontFeaturesVar::get_new(ctx) {
|
||||
self.features = new_ctx.clone();
|
||||
(self.set_feature)(&mut self.features, self.var.get(ctx.vars).clone());
|
||||
(self.set_feature)(&mut self.features, self.var.get_clone(ctx));
|
||||
self.version = self.version.wrapping_add(1);
|
||||
is_new = true;
|
||||
} else if let Some(value) = self.var.get_new(ctx.vars) {
|
||||
} else if let Some(value) = self.var.get_new(ctx) {
|
||||
(self.set_feature)(&mut self.features, value.clone());
|
||||
self.version = self.version.wrapping_add(1);
|
||||
is_new = true;
|
||||
|
@ -615,7 +615,9 @@ pub struct TextContext<'a> {
|
|||
}
|
||||
impl<'a> TextContext<'a> {
|
||||
/// Borrow or copy all the text contextual values.
|
||||
pub fn get(vars: &'a VarsRead) -> Self {
|
||||
pub fn get<Vr: AsRef<VarsRead>>(vars: &'a Vr) -> Self {
|
||||
let vars = vars.as_ref();
|
||||
|
||||
TextContext {
|
||||
font_family: FontFamilyVar::get(vars),
|
||||
font_style: *FontStyleVar::get(vars),
|
||||
|
@ -646,7 +648,8 @@ impl<'a> TextContext<'a> {
|
|||
}
|
||||
|
||||
/// Gets the properties that affect the font face.
|
||||
pub fn font_face(vars: &'a VarsRead) -> (&'a [FontName], FontStyle, FontWeight, FontStretch) {
|
||||
pub fn font_face<Vr: AsRef<VarsRead>>(vars: &'a Vr) -> (&'a [FontName], FontStyle, FontWeight, FontStretch) {
|
||||
let vars = vars.as_ref();
|
||||
(
|
||||
FontFamilyVar::get(vars),
|
||||
*FontStyleVar::get(vars),
|
||||
|
@ -655,7 +658,8 @@ impl<'a> TextContext<'a> {
|
|||
)
|
||||
}
|
||||
/// Gets [`font_face`](Self::font_face) if any of the properties updated.
|
||||
pub fn font_face_update(vars: &'a Vars) -> Option<(&'a [FontName], FontStyle, FontWeight, FontStretch)> {
|
||||
pub fn font_face_update<Vw: AsRef<Vars>>(vars: &'a Vw) -> Option<(&'a [FontName], FontStyle, FontWeight, FontStretch)> {
|
||||
let vars = vars.as_ref();
|
||||
if FontFamilyVar::is_new(vars) || FontStyleVar::is_new(vars) || FontWeightVar::is_new(vars) || FontStretchVar::is_new(vars) {
|
||||
Some(Self::font_face(vars))
|
||||
} else {
|
||||
|
@ -665,26 +669,30 @@ impl<'a> TextContext<'a> {
|
|||
|
||||
/// Gets the properties that affect the text characters.
|
||||
#[inline]
|
||||
pub fn text(vars: &'a VarsRead) -> (TextTransformFn, WhiteSpace) {
|
||||
(TextTransformVar::get(vars).clone(), *WhiteSpaceVar::get(vars))
|
||||
pub fn text<Vr: WithVarsRead>(vars: &'a Vr) -> (TextTransformFn, WhiteSpace) {
|
||||
vars.with(|vars| (TextTransformVar::get(vars).clone(), *WhiteSpaceVar::get(vars)))
|
||||
}
|
||||
/// Gets [`text`](Self::text) if any of the properties updated.
|
||||
pub fn text_update(vars: &'a Vars) -> Option<(TextTransformFn, WhiteSpace)> {
|
||||
if TextTransformVar::is_new(vars) || WhiteSpaceVar::is_new(vars) {
|
||||
Some(Self::text(vars))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
pub fn text_update<Vw: WithVars>(vars: &'a Vw) -> Option<(TextTransformFn, WhiteSpace)> {
|
||||
vars.with(|vars| {
|
||||
if TextTransformVar::is_new(vars) || WhiteSpaceVar::is_new(vars) {
|
||||
Some(Self::text(vars))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets the properties that affect the sized font. The [`Length`] is `font_size`.
|
||||
#[inline]
|
||||
pub fn font(vars: &'a VarsRead) -> (Length, &'a FontVariations) {
|
||||
pub fn font<Vr: AsRef<VarsRead>>(vars: &'a Vr) -> (Length, &'a FontVariations) {
|
||||
let vars = vars.as_ref();
|
||||
(*FontSizeVar::get(vars), FontVariationsVar::get(vars))
|
||||
}
|
||||
/// Gets [`font`](Self::font) if any of the properties updated.
|
||||
#[inline]
|
||||
pub fn font_update(vars: &'a Vars) -> Option<(Length, &'a FontVariations)> {
|
||||
pub fn font_update<Vw: AsRef<Vars>>(vars: &'a Vw) -> Option<(Length, &'a FontVariations)> {
|
||||
let vars = vars.as_ref();
|
||||
if FontSizeVar::is_new(vars) || FontVariationsVar::is_new(vars) {
|
||||
Some(Self::font(vars))
|
||||
} else {
|
||||
|
@ -694,29 +702,31 @@ impl<'a> TextContext<'a> {
|
|||
|
||||
/// Gets the property that affect color.
|
||||
#[inline]
|
||||
pub fn color(vars: &'a VarsRead) -> Rgba {
|
||||
pub fn color<Vr: AsRef<VarsRead>>(vars: &'a Vr) -> Rgba {
|
||||
*TextColorVar::get(vars)
|
||||
}
|
||||
/// Gets [`color`](Self::color) if the property updated.
|
||||
#[inline]
|
||||
pub fn color_update(vars: &'a Vars) -> Option<Rgba> {
|
||||
TextColorVar::get_new(vars).copied()
|
||||
pub fn color_update<Vw: WithVars>(vars: &'a Vw) -> Option<Rgba> {
|
||||
vars.with(|vars| TextColorVar::get_new(vars).copied())
|
||||
}
|
||||
|
||||
/// Gets the properties that affects what font synthesis is used.
|
||||
#[inline]
|
||||
pub fn font_synthesis(vars: &'a VarsRead) -> (FontSynthesis, FontStyle, FontWeight) {
|
||||
(*FontSynthesisVar::get(vars), *FontStyleVar::get(vars), *FontWeightVar::get(vars))
|
||||
pub fn font_synthesis<Vr: WithVarsRead>(vars: &'a Vr) -> (FontSynthesis, FontStyle, FontWeight) {
|
||||
vars.with(|vars| (*FontSynthesisVar::get(vars), *FontStyleVar::get(vars), *FontWeightVar::get(vars)))
|
||||
}
|
||||
|
||||
/// Gets [`font_synthesis`](Self::font_synthesis) if any of the properties changed.
|
||||
#[inline]
|
||||
pub fn font_synthesis_update(vars: &'a Vars) -> Option<(FontSynthesis, FontStyle, FontWeight)> {
|
||||
if FontSynthesisVar::is_new(vars) || FontStyleVar::is_new(vars) || FontWeightVar::is_new(vars) {
|
||||
Some(Self::font_synthesis(vars))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
pub fn font_synthesis_update<Vw: WithVars>(vars: &'a Vw) -> Option<(FontSynthesis, FontStyle, FontWeight)> {
|
||||
vars.with(|vars| {
|
||||
if FontSynthesisVar::is_new(vars) || FontStyleVar::is_new(vars) || FontWeightVar::is_new(vars) {
|
||||
Some(Self::font_synthesis(vars))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<'a> Clone for TextContext<'a> {
|
||||
|
|
|
@ -22,13 +22,13 @@ pub fn transform(child: impl UiNode, transform: impl IntoVar<Transform>) -> impl
|
|||
{
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
if self.transform.is_new(ctx.vars) {
|
||||
if self.transform.is_new(ctx) {
|
||||
ctx.updates.render_update();
|
||||
}
|
||||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.layout_transform = self.transform.get(ctx.vars).to_layout(final_size, ctx);
|
||||
self.layout_transform = self.transform.get(ctx).to_layout(final_size, ctx);
|
||||
self.child.arrange(ctx, final_size);
|
||||
}
|
||||
|
||||
|
@ -170,14 +170,14 @@ pub fn transform_origin(child: impl UiNode, origin: impl IntoVar<Point>) -> impl
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, O: Var<Point>> UiNode for TransformOriginNode<C, O> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.origin.is_new(ctx.vars) {
|
||||
if self.origin.is_new(ctx) {
|
||||
ctx.updates.render_update();
|
||||
}
|
||||
self.child.update(ctx);
|
||||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.layout_origin = self.origin.get(ctx.vars).to_layout(final_size, ctx);
|
||||
self.layout_origin = self.origin.get(ctx).to_layout(final_size, ctx);
|
||||
self.child.arrange(ctx, final_size);
|
||||
}
|
||||
|
||||
|
|
|
@ -200,12 +200,12 @@ where
|
|||
V: Var<K::Type>,
|
||||
{
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
ctx.widget_state.set::<K>(self.var.get(ctx.vars).clone());
|
||||
ctx.widget_state.set::<K>(self.var.get(ctx).clone());
|
||||
self.child.init(ctx);
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if let Some(new) = self.var.get_new(ctx.vars) {
|
||||
if let Some(new) = self.var.get_new(ctx) {
|
||||
ctx.widget_state.set::<K>(new.clone());
|
||||
}
|
||||
self.child.update(ctx);
|
||||
|
@ -279,12 +279,12 @@ mod tests {
|
|||
impl<C: UiNode, V: Var<u8>> UiNode for TestVarProbeNode<C, V> {
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.init(ctx);
|
||||
self.value.set(ctx.vars, *TestVar::get(ctx.vars)).expect("probe var is read-only");
|
||||
self.value.set(ctx.vars, *TestVar::get(ctx)).expect("probe var is read-only");
|
||||
}
|
||||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.child.update(ctx);
|
||||
if let Some(&new) = TestVar::get_new(ctx.vars) {
|
||||
if let Some(&new) = TestVar::get_new(ctx) {
|
||||
self.value.set(ctx.vars, new).expect("probe var is read-only");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -316,7 +316,7 @@ pub fn clip_to_bounds(child: impl UiNode, clip: impl IntoVar<bool>) -> impl UiNo
|
|||
#[impl_ui_node(child)]
|
||||
impl<T: UiNode, S: Var<bool>> UiNode for ClipToBoundsNode<T, S> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.clip.is_new(ctx.vars) {
|
||||
if self.clip.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
|
||||
|
@ -329,7 +329,7 @@ pub fn clip_to_bounds(child: impl UiNode, clip: impl IntoVar<bool>) -> impl UiNo
|
|||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
if *self.clip.get(ctx.vars) {
|
||||
if *self.clip.get(ctx) {
|
||||
frame.push_simple_clip(self.bounds, |frame| self.child.render(ctx, frame));
|
||||
} else {
|
||||
self.child.render(ctx, frame);
|
||||
|
|
|
@ -9,7 +9,7 @@ pub fn fill_color(color: impl IntoVar<Rgba>) -> impl UiNode {
|
|||
#[impl_ui_node(none)]
|
||||
impl<C: Var<Rgba>> UiNode for FillColorNode<C> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.color.is_new(ctx.vars) {
|
||||
if self.color.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub fn fill_color(color: impl IntoVar<Rgba>) -> impl UiNode {
|
|||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
frame.push_color(LayoutRect::from_size(self.final_size), (*self.color.get(ctx.vars)).into());
|
||||
frame.push_color(LayoutRect::from_size(self.final_size), (self.color.copy(ctx)).into());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,21 +74,21 @@ where
|
|||
|
||||
#[UiNode]
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.axis.is_new(ctx.vars) || self.stops.is_new(ctx.vars) || self.extend_mode.is_new(ctx.vars) {
|
||||
if self.axis.is_new(ctx) || self.stops.is_new(ctx) || self.extend_mode.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
}
|
||||
#[UiNode]
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.final_size = final_size;
|
||||
self.render_line = self.axis.get(ctx.vars).layout(final_size, ctx);
|
||||
self.render_line = self.axis.get(ctx).layout(final_size, ctx);
|
||||
|
||||
let length = self.render_line.length();
|
||||
|
||||
self.stops.get(ctx.vars).layout_linear(
|
||||
self.stops.get(ctx).layout_linear(
|
||||
length,
|
||||
ctx,
|
||||
*self.extend_mode.get(ctx.vars),
|
||||
*self.extend_mode.get(ctx),
|
||||
&mut self.render_line,
|
||||
&mut self.render_stops,
|
||||
);
|
||||
|
@ -99,7 +99,7 @@ where
|
|||
LayoutRect::from_size(self.final_size),
|
||||
self.render_line,
|
||||
&self.render_stops,
|
||||
(*self.extend_mode.get(ctx.vars)).into(),
|
||||
(*self.extend_mode.get(ctx)).into(),
|
||||
self.final_size,
|
||||
LayoutSize::zero(),
|
||||
);
|
||||
|
@ -128,14 +128,14 @@ where
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.g.update(ctx);
|
||||
|
||||
if self.tile_size.is_new(ctx.vars) || self.tile_spacing.is_new(ctx.vars) {
|
||||
if self.tile_size.is_new(ctx) || self.tile_spacing.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
self.render_tile_size = self.tile_size.get(ctx.vars).to_layout(final_size, ctx);
|
||||
self.render_tile_spacing = self.tile_spacing.get(ctx.vars).to_layout(final_size, ctx);
|
||||
self.render_tile_size = self.tile_size.get(ctx).to_layout(final_size, ctx);
|
||||
self.render_tile_spacing = self.tile_spacing.get(ctx).to_layout(final_size, ctx);
|
||||
self.g.arrange(ctx, self.render_tile_size);
|
||||
self.g.final_size = final_size;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ where
|
|||
LayoutRect::from_size(self.g.final_size),
|
||||
self.g.render_line,
|
||||
&self.g.render_stops,
|
||||
(*self.g.extend_mode.get(ctx.vars)).into(),
|
||||
self.g.extend_mode.copy(ctx).into(),
|
||||
self.render_tile_size,
|
||||
self.render_tile_spacing,
|
||||
);
|
||||
|
|
|
@ -34,7 +34,7 @@ where
|
|||
|
||||
#[UiNode]
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.spacing.is_new(ctx.vars) {
|
||||
if self.spacing.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
self.children.update_all(ctx);
|
||||
|
@ -48,7 +48,7 @@ where
|
|||
let (total_len, max_ort_len) = D::lengths_mut(&mut total_size);
|
||||
let spacing = self
|
||||
.spacing
|
||||
.get(ctx.vars)
|
||||
.get(ctx)
|
||||
.to_layout(LayoutLength::new(D::length(available_size)), ctx)
|
||||
.get();
|
||||
let mut first = true;
|
||||
|
|
|
@ -147,11 +147,7 @@ pub mod uniform_grid {
|
|||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.children.update_all(ctx);
|
||||
|
||||
if self.columns.is_new(ctx.vars)
|
||||
|| self.rows.is_new(ctx.vars)
|
||||
|| self.first_column.is_new(ctx.vars)
|
||||
|| self.spacing.is_new(ctx.vars)
|
||||
{
|
||||
if self.columns.is_new(ctx) || self.rows.is_new(ctx) || self.first_column.is_new(ctx) || self.spacing.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +155,7 @@ pub mod uniform_grid {
|
|||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
let (columns, rows) = self.grid_len(ctx.vars);
|
||||
|
||||
let layout_spacing = self.spacing.get(ctx.vars).to_layout(available_size, ctx);
|
||||
let layout_spacing = self.spacing.get(ctx).to_layout(available_size, ctx);
|
||||
|
||||
let available_size = LayoutSize::new(
|
||||
(available_size.width - layout_spacing.column / 2.0) / columns,
|
||||
|
@ -182,7 +178,7 @@ pub mod uniform_grid {
|
|||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
let (columns, rows) = self.grid_len(ctx.vars);
|
||||
|
||||
let layout_spacing = self.spacing.get(ctx.vars).to_layout(final_size, ctx);
|
||||
let layout_spacing = self.spacing.get(ctx).to_layout(final_size, ctx);
|
||||
|
||||
let cell_size = LayoutSize::new(
|
||||
(final_size.width - layout_spacing.column * (columns - 1.0)) / columns,
|
||||
|
@ -192,7 +188,7 @@ pub mod uniform_grid {
|
|||
|
||||
self.children.arrange_all(ctx, |_, _| cell_size);
|
||||
|
||||
let mut first_column = *self.first_column.get(ctx.vars) as f32;
|
||||
let mut first_column = self.first_column.copy(ctx) as f32;
|
||||
if first_column >= columns {
|
||||
first_column = 0.0;
|
||||
}
|
||||
|
|
|
@ -58,18 +58,18 @@ pub mod line_w {
|
|||
S: Var<LineStyle>,
|
||||
{
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.width.is_new(ctx.vars) || self.length.is_new(ctx.vars) || self.orientation.is_new(ctx.vars) {
|
||||
if self.width.is_new(ctx) || self.length.is_new(ctx) || self.orientation.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
if self.color.is_new(ctx.vars) || self.style.is_new(ctx.vars) {
|
||||
if self.color.is_new(ctx) || self.style.is_new(ctx) {
|
||||
ctx.updates.render();
|
||||
}
|
||||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_space: LayoutSize) -> LayoutSize {
|
||||
let (width, height) = match *self.orientation.get(ctx.vars) {
|
||||
LineOrientation::Horizontal => (self.length.get(ctx.vars), self.width.get(ctx.vars)),
|
||||
LineOrientation::Vertical => (self.width.get(ctx.vars), self.length.get(ctx.vars)),
|
||||
let (width, height) = match *self.orientation.get(ctx) {
|
||||
LineOrientation::Horizontal => (self.length.get(ctx), self.width.get(ctx)),
|
||||
LineOrientation::Vertical => (self.width.get(ctx), self.length.get(ctx)),
|
||||
};
|
||||
|
||||
let width = width.to_layout(LayoutLength::new(available_space.width), ctx);
|
||||
|
@ -84,9 +84,9 @@ pub mod line_w {
|
|||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
let bounds = LayoutRect::from_size(self.bounds);
|
||||
let orientation = *self.orientation.get(ctx.vars);
|
||||
let color = *self.color.get(ctx.vars);
|
||||
let style = *self.style.get(ctx.vars);
|
||||
let orientation = *self.orientation.get(ctx);
|
||||
let color = *self.color.get(ctx);
|
||||
let style = *self.style.get(ctx);
|
||||
frame.push_line(bounds, orientation, color.into(), style);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,13 +27,13 @@ pub mod switch {
|
|||
impl<I: Var<usize>, W: UiNodeList> UiNode for SwitchNode<I, W> {
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
self.options.update_all(ctx);
|
||||
if self.index.is_new(ctx.vars) {
|
||||
if self.index.is_new(ctx) {
|
||||
ctx.updates.layout();
|
||||
}
|
||||
}
|
||||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
let index = *self.index.get(ctx.vars);
|
||||
let index = self.index.copy(ctx);
|
||||
if index < self.options.len() {
|
||||
self.options.widget_measure(index, ctx, available_size)
|
||||
} else {
|
||||
|
@ -42,20 +42,20 @@ pub mod switch {
|
|||
}
|
||||
|
||||
fn arrange(&mut self, ctx: &mut LayoutContext, final_size: LayoutSize) {
|
||||
let index = *self.index.get(ctx.vars);
|
||||
let index = self.index.copy(ctx);
|
||||
if index < self.options.len() {
|
||||
self.options.widget_arrange(index, ctx, final_size)
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&self, ctx: &mut RenderContext, frame: &mut FrameBuilder) {
|
||||
let index = *self.index.get(ctx.vars);
|
||||
let index = self.index.copy(ctx);
|
||||
if index < self.options.len() {
|
||||
self.options.widget_render(index, ctx, frame)
|
||||
}
|
||||
}
|
||||
fn render_update(&self, ctx: &mut RenderContext, update: &mut FrameUpdate) {
|
||||
let index = *self.index.get(ctx.vars);
|
||||
let index = self.index.copy(ctx);
|
||||
if index < self.options.len() {
|
||||
self.options.widget_render_update(index, ctx, update)
|
||||
}
|
||||
|
|
|
@ -189,16 +189,16 @@ impl<T: Var<Text>> TextNode<T> {
|
|||
#[impl_ui_node(none)]
|
||||
impl<T: Var<Text>> UiNode for TextNode<T> {
|
||||
fn init(&mut self, ctx: &mut WidgetContext) {
|
||||
let (family, style, weight, stretch) = TextContext::font_face(ctx.vars);
|
||||
let (family, style, weight, stretch) = TextContext::font_face(ctx);
|
||||
|
||||
// TODO use the full list.
|
||||
let font_face = ctx.services.fonts().get_list(family, style, weight, stretch).best().clone();
|
||||
self.synthesis_used = *FontSynthesisVar::get(ctx.vars) & font_face.synthesis_for(style, weight);
|
||||
self.synthesis_used = *FontSynthesisVar::get(ctx) & font_face.synthesis_for(style, weight);
|
||||
self.font_face = Some(font_face);
|
||||
|
||||
let text = self.text_var.get(ctx.vars).clone();
|
||||
let text = TextTransformVar::get(ctx.vars).transform(text);
|
||||
let text = WhiteSpaceVar::get(ctx.vars).transform(text);
|
||||
let text = self.text_var.get_clone(ctx);
|
||||
let text = TextTransformVar::get(ctx).transform(text);
|
||||
let text = WhiteSpaceVar::get(ctx).transform(text);
|
||||
self.text = SegmentedText::new(text)
|
||||
}
|
||||
|
||||
|
@ -211,8 +211,8 @@ impl<T: Var<Text>> UiNode for TextNode<T> {
|
|||
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
// update `self.text`, affects shaping and layout
|
||||
if let Some(text) = self.text_var.get_new(ctx.vars) {
|
||||
let (text_transform, white_space) = TextContext::text(ctx.vars);
|
||||
if let Some(text) = self.text_var.get_new(ctx) {
|
||||
let (text_transform, white_space) = TextContext::text(ctx);
|
||||
let text = text_transform.transform(text.clone());
|
||||
let text = white_space.transform(text);
|
||||
if self.text.text() != text {
|
||||
|
@ -221,8 +221,8 @@ impl<T: Var<Text>> UiNode for TextNode<T> {
|
|||
|
||||
ctx.updates.layout();
|
||||
}
|
||||
} else if let Some((text_transform, white_space)) = TextContext::text_update(ctx.vars) {
|
||||
let text = self.text_var.get(ctx.vars).clone();
|
||||
} else if let Some((text_transform, white_space)) = TextContext::text_update(ctx) {
|
||||
let text = self.text_var.get_clone(ctx);
|
||||
let text = text_transform.transform(text);
|
||||
let text = white_space.transform(text);
|
||||
if self.text.text() != text {
|
||||
|
@ -234,7 +234,7 @@ impl<T: Var<Text>> UiNode for TextNode<T> {
|
|||
}
|
||||
|
||||
// update `self.font_face`, affects shaping and layout
|
||||
if let Some((font_family, font_style, font_weight, font_stretch)) = TextContext::font_face_update(ctx.vars) {
|
||||
if let Some((font_family, font_style, font_weight, font_stretch)) = TextContext::font_face_update(ctx) {
|
||||
let face = ctx
|
||||
.services
|
||||
.fonts()
|
||||
|
@ -243,7 +243,7 @@ impl<T: Var<Text>> UiNode for TextNode<T> {
|
|||
.clone();
|
||||
|
||||
if !self.font_face.as_ref().map(|f| f.ptr_eq(&face)).unwrap_or_default() {
|
||||
self.synthesis_used = *FontSynthesisVar::get(ctx.vars) & face.synthesis_for(font_style, font_weight);
|
||||
self.synthesis_used = *FontSynthesisVar::get(ctx) & face.synthesis_for(font_style, font_weight);
|
||||
self.font_face = Some(face);
|
||||
self.font = None;
|
||||
self.shaped_text = ShapedText::default();
|
||||
|
@ -253,7 +253,7 @@ impl<T: Var<Text>> UiNode for TextNode<T> {
|
|||
}
|
||||
|
||||
// update `self.font_instance`, affects shaping and layout
|
||||
if TextContext::font_update(ctx.vars).is_some() {
|
||||
if TextContext::font_update(ctx).is_some() {
|
||||
self.font = None;
|
||||
self.shaped_text = ShapedText::default();
|
||||
ctx.updates.layout();
|
||||
|
@ -262,12 +262,12 @@ impl<T: Var<Text>> UiNode for TextNode<T> {
|
|||
// TODO features, spacing, breaking.
|
||||
|
||||
// update `self.color`
|
||||
if TextContext::color_update(ctx.vars).is_some() {
|
||||
if TextContext::color_update(ctx).is_some() {
|
||||
ctx.updates.render();
|
||||
}
|
||||
|
||||
// update `self.font_synthesis`
|
||||
if let Some((synthesis_allowed, style, weight)) = TextContext::font_synthesis_update(ctx.vars) {
|
||||
if let Some((synthesis_allowed, style, weight)) = TextContext::font_synthesis_update(ctx) {
|
||||
if let Some(face) = &self.font_face {
|
||||
let synthesis_used = synthesis_allowed & face.synthesis_for(style, weight);
|
||||
if synthesis_used != self.synthesis_used {
|
||||
|
@ -280,7 +280,7 @@ impl<T: Var<Text>> UiNode for TextNode<T> {
|
|||
|
||||
fn measure(&mut self, ctx: &mut LayoutContext, available_size: LayoutSize) -> LayoutSize {
|
||||
if self.font.is_none() {
|
||||
let (size, variations) = TextContext::font(ctx.vars);
|
||||
let (size, variations) = TextContext::font(ctx);
|
||||
let size = size.to_layout(LayoutLength::new(available_size.width), ctx);
|
||||
self.font = Some(
|
||||
self.font_face
|
||||
|
@ -317,7 +317,7 @@ impl<T: Var<Text>> UiNode for TextNode<T> {
|
|||
LayoutRect::from_size(self.size),
|
||||
self.shaped_text.glyphs(),
|
||||
self.font.as_ref().expect("font not initied in render"),
|
||||
RenderColor::from(*TextColorVar::get(ctx.vars)),
|
||||
RenderColor::from(*TextColorVar::get(ctx)),
|
||||
self.synthesis_used,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ pub enum View<U: UiNode> {
|
|||
/// }.boxed())
|
||||
/// }
|
||||
/// State::Counting => {
|
||||
/// if *n.get(ctx.vars) > 0 {
|
||||
/// if n.copy(ctx) > 0 {
|
||||
/// // text updates automatically when `n` updates
|
||||
/// // se we can continue using the same UI.
|
||||
///
|
||||
|
@ -132,7 +132,7 @@ where
|
|||
|
||||
#[UiNode]
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.data.is_new(ctx.vars) {
|
||||
if self.data.is_new(ctx) {
|
||||
self.refresh_child(ctx);
|
||||
}
|
||||
self.child.update(ctx);
|
||||
|
|
|
@ -300,7 +300,7 @@ pub mod window {
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, V: Var<$Type>> [<Window $ident:camel Node>] <C, V> {
|
||||
fn set(&mut self, ctx: &mut WidgetContext) {
|
||||
let $ident = self.$ident.get(ctx.vars).clone();
|
||||
let $ident = self.$ident.get_clone(ctx);
|
||||
ctx.window_state
|
||||
.get::<WindowVars>()
|
||||
.expect("no `WindowVars` in `window_state`")
|
||||
|
@ -316,14 +316,14 @@ pub mod window {
|
|||
|
||||
#[UiNode]
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.$ident.is_new(ctx.vars) {
|
||||
if self.$ident.is_new(ctx) {
|
||||
self.set(ctx);
|
||||
} else if let Some($ident) = ctx
|
||||
.window_state
|
||||
.get::<WindowVars>()
|
||||
.expect("no `WindowVars` in `window_state`")
|
||||
.$ident()
|
||||
.get_new(ctx.vars) {
|
||||
.get_new(ctx) {
|
||||
let _ = self.$ident.set_ne(ctx.vars, $ident.clone());
|
||||
}
|
||||
self.child.update(ctx);
|
||||
|
@ -375,16 +375,16 @@ pub mod window {
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, V: Var<$Type>> [<Window $ident:camel Node>] <C, V> {
|
||||
fn set(&mut self, ctx: &mut WidgetContext) {
|
||||
let $ident = *self.$ident.get(ctx.vars);
|
||||
let $ident = self.$ident.copy(ctx);
|
||||
let [<$ident var>] = ctx.window_state.get::<WindowVars>().expect("no `WindowVars` in `window_state`").$ident();
|
||||
|
||||
if $ident.$member_a.is_finite() {
|
||||
if $ident.$member_b.is_finite() {
|
||||
[<$ident var>].set_ne(ctx.vars, $ident);
|
||||
} else if $ident.$member_a != [<$ident var>].get(ctx.vars).$member_a {
|
||||
} else if $ident.$member_a != [<$ident var>].get(ctx).$member_a {
|
||||
[<$ident var>].modify(ctx.vars, move |v|v.$member_a = $ident.$member_a);
|
||||
}
|
||||
} else if $ident.$member_b.is_finite() && $ident.$member_b != [<$ident var>].get(ctx.vars).$member_b {
|
||||
} else if $ident.$member_b.is_finite() && $ident.$member_b != [<$ident var>].get(ctx).$member_b {
|
||||
[<$ident var>].modify(ctx.vars, move |v|v.$member_b = $ident.$member_b);
|
||||
}
|
||||
}
|
||||
|
@ -397,14 +397,14 @@ pub mod window {
|
|||
|
||||
#[UiNode]
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.$ident.is_new(ctx.vars) {
|
||||
if self.$ident.is_new(ctx) {
|
||||
self.set(ctx);
|
||||
} else if let Some($ident) = ctx
|
||||
.window_state
|
||||
.get::<WindowVars>()
|
||||
.expect("no `WindowVars` in `window_state`")
|
||||
.$ident()
|
||||
.get_new(ctx.vars)
|
||||
.get_new(ctx)
|
||||
{
|
||||
let _ = self.$ident.set_ne(ctx.vars, $ident.clone());
|
||||
}
|
||||
|
@ -442,14 +442,14 @@ pub mod window {
|
|||
#[impl_ui_node(child)]
|
||||
impl<C: UiNode, V: Var<Length>> [<Window $ident:camel Node>]<C, V> {
|
||||
fn set(&mut self, ctx: &mut WidgetContext) {
|
||||
let $ident = *self.$ident.get(ctx.vars);
|
||||
let $ident = *self.$ident.get(ctx);
|
||||
if $ident.is_finite() {
|
||||
let $var = ctx
|
||||
.window_state
|
||||
.get::<WindowVars>()
|
||||
.expect("no `WindowVars` in `window_state`")
|
||||
.$var();
|
||||
if $ident != $var.get(ctx.vars).$member {
|
||||
if $ident != $var.get(ctx).$member {
|
||||
$var.modify(ctx.vars, move |s| s.$member = $ident);
|
||||
}
|
||||
}
|
||||
|
@ -463,14 +463,14 @@ pub mod window {
|
|||
|
||||
#[UiNode]
|
||||
fn update(&mut self, ctx: &mut WidgetContext) {
|
||||
if self.$ident.is_new(ctx.vars) {
|
||||
if self.$ident.is_new(ctx) {
|
||||
self.set(ctx);
|
||||
} else if let Some($var) = ctx
|
||||
.window_state
|
||||
.get::<WindowVars>()
|
||||
.expect("no `WindowVars` in `window_state`")
|
||||
.$var()
|
||||
.get_new(ctx.vars)
|
||||
.get_new(ctx)
|
||||
{
|
||||
let _ = self.$ident.set_ne(ctx.vars, $var.$member);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue