Started implemented Vars adapters and more varaible helper methods.

This commit is contained in:
Samuel Guerra 2021-06-18 19:11:25 -03:00
parent 2537bcda95
commit 61709bc6d1
47 changed files with 1492 additions and 1230 deletions

View File

@ -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);

View File

@ -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",

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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,

View File

@ -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)]

View File

@ -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);
}
}

View File

@ -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`.

View File

@ -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

View File

@ -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)
}
}

View File

@ -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
}
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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)
}

View File

@ -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>;

View File

@ -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.

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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,
);

View File

@ -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
}

View File

@ -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);

View File

@ -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 {

View File

@ -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!()
/// }
/// }

View File

@ -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));

View File

@ -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() {

View File

@ -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 {

View File

@ -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!();
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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> {

View File

@ -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);
}

View File

@ -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");
}
}

View File

@ -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);

View File

@ -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());
}
}

View File

@ -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,
);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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)
}

View File

@ -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,
);
}

View File

@ -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);

View File

@ -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);
}