mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-23 12:43:08 +00:00
nested state
This commit is contained in:
parent
f4689a4e27
commit
7c30d93a3d
5 changed files with 270 additions and 30 deletions
|
@ -304,7 +304,7 @@ flowchart TB
|
|||
end
|
||||
```
|
||||
|
||||
To help in building a Dom, native core provides four traits: State, ChildDepState, ParentDepState, and NodeDepState.
|
||||
To help in building a Dom, native core provides four traits: State, ChildDepState, ParentDepState, and NodeDepState and a RealDom struct.
|
||||
|
||||
```rust
|
||||
use dioxus_native_core::node_ref::*;
|
||||
|
@ -436,6 +436,48 @@ struct ToyState {
|
|||
}
|
||||
```
|
||||
|
||||
Now that we have our state, we can put it to use in our dom. Re can update the dom with update_state to update the structure of the dom (adding, removing, and chaning properties of nodes) and then apply_mutations to update the ToyState for each of the nodes that changed.
|
||||
```rust
|
||||
fn main(){
|
||||
fn app(cx: Scope) -> Element {
|
||||
cx.render(rsx!{
|
||||
div{
|
||||
color: "red",
|
||||
"hello world"
|
||||
}
|
||||
})
|
||||
}
|
||||
let vdom = VirtualDom::new(app);
|
||||
let rdom: RealDom<ToyState> = RealDom::new();
|
||||
|
||||
let mutations = dom.rebuild();
|
||||
// update the structure of the real_dom tree
|
||||
let to_update = rdom.apply_mutations(vec![mutations]);
|
||||
let mut ctx = AnyMap::new();
|
||||
// set the font size to 3.3
|
||||
ctx.insert(3.3);
|
||||
// update the ToyState for nodes in the real_dom tree
|
||||
let _to_rerender = rdom.update_state(&dom, to_update, ctx).unwrap();
|
||||
|
||||
// we need to run the vdom in a async runtime
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()?
|
||||
.block_on(async {
|
||||
loop{
|
||||
let wait = vdom.wait_for_work();
|
||||
let mutations = vdom.work_with_deadline(|| false);
|
||||
let to_update = rdom.apply_mutations(mutations);
|
||||
let mut ctx = AnyMap::new();
|
||||
ctx.insert(3.3);
|
||||
let _to_rerender = rdom.update_state(vdom, to_update, ctx).unwrap();
|
||||
|
||||
// render...
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## Layout
|
||||
For most platforms the layout of the Elements will stay the same. The layout_attributes module provides a way to apply html attributes to a stretch layout style.
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ mod sorted_slice;
|
|||
|
||||
use dioxus_native_core::state::MemberId;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::format_ident;
|
||||
use quote::{quote, ToTokens, __private::Span};
|
||||
use sorted_slice::StrSlice;
|
||||
use syn::{
|
||||
|
@ -26,7 +27,10 @@ enum DepKind {
|
|||
Parent,
|
||||
}
|
||||
|
||||
#[proc_macro_derive(State, attributes(node_dep_state, child_dep_state, parent_dep_state))]
|
||||
#[proc_macro_derive(
|
||||
State,
|
||||
attributes(node_dep_state, child_dep_state, parent_dep_state, state)
|
||||
)]
|
||||
pub fn state_macro_derive(input: TokenStream) -> TokenStream {
|
||||
let ast = syn::parse(input).unwrap();
|
||||
impl_derive_macro(&ast)
|
||||
|
@ -89,8 +93,51 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||
|
||||
let type_name_str = type_name.to_string();
|
||||
|
||||
let child_states = &state_strct.child_states;
|
||||
|
||||
let member_size = state_strct.state_members.len();
|
||||
|
||||
let child_state_ty = child_states.iter().map(|m| &m.ty);
|
||||
let child_state_idents: Vec<_> = child_states.iter().map(|m| &m.ident).collect();
|
||||
let sum_const_declarations = child_state_ty.clone().enumerate().map(|(i, ty)| {
|
||||
let ident = format_ident!("__{}_SUM_{}", i, type_name.to_string());
|
||||
let ident_minus = format_ident!("__{}_SUM_{}_minus", i, type_name.to_string());
|
||||
if i == 0 {
|
||||
quote!(const #ident_minus: usize = #member_size + #ty::SIZE - 1;
|
||||
const #ident: usize = #member_size + #ty::SIZE;)
|
||||
} else {
|
||||
let prev_ident = format_ident!("__{}_SUM_{}", i - 1, type_name.to_string());
|
||||
quote!(const #ident_minus: usize = #prev_ident + #ty::SIZE - 1;
|
||||
const #ident: usize = #prev_ident + #ty::SIZE;)
|
||||
}
|
||||
});
|
||||
let sum_idents: Vec<_> = std::iter::once(quote!(#member_size))
|
||||
.chain((0..child_states.len()).map(|i| {
|
||||
let ident = format_ident!("__{}_SUM_{}", i, type_name.to_string());
|
||||
quote!(#ident)
|
||||
}))
|
||||
.collect();
|
||||
|
||||
let child_state_ranges: Vec<_> = (0..child_state_ty.len())
|
||||
.map(|i| {
|
||||
let current = format_ident!("__{}_SUM_{}_minus", i, type_name.to_string());
|
||||
let previous = if i == 0 {
|
||||
quote!(#member_size)
|
||||
} else {
|
||||
let ident = format_ident!("__{}_SUM_{}", i - 1, type_name.to_string());
|
||||
quote!(#ident)
|
||||
};
|
||||
quote!(#previous..=#current)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let gen = quote! {
|
||||
#(
|
||||
#sum_const_declarations
|
||||
)*
|
||||
impl State for #type_name{
|
||||
const SIZE: usize = #member_size #( + #child_state_ty::SIZE)*;
|
||||
|
||||
fn update_node_dep_state<'a>(
|
||||
&'a mut self,
|
||||
ty: dioxus_native_core::state::MemberId,
|
||||
|
@ -99,10 +146,26 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||
ctx: &anymap::AnyMap,
|
||||
) -> Option<dioxus_native_core::state::NodeStatesChanged>{
|
||||
use dioxus_native_core::state::NodeDepState as _;
|
||||
use dioxus_native_core::state::State as _;
|
||||
match ty.0{
|
||||
#(
|
||||
#node_ids => #node_dep_state_fields,
|
||||
)*
|
||||
#(
|
||||
#child_state_ranges => {
|
||||
self.#child_state_idents.update_node_dep_state(
|
||||
ty - #sum_idents,
|
||||
node,
|
||||
vdom,
|
||||
ctx,
|
||||
).map(|mut changed|{
|
||||
for id in &mut changed.node_dep{
|
||||
*id += #sum_idents;
|
||||
}
|
||||
changed
|
||||
})
|
||||
}
|
||||
)*
|
||||
_ => panic!("{:?} not in {}", ty, #type_name_str),
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +183,25 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||
#(
|
||||
#parent_ids => #parent_dep_state_fields,
|
||||
)*
|
||||
#(
|
||||
#child_state_ranges => {
|
||||
self.#child_state_idents.update_parent_dep_state(
|
||||
ty - #sum_idents,
|
||||
node,
|
||||
vdom,
|
||||
parent.map(|p| &p.#child_state_idents),
|
||||
ctx,
|
||||
).map(|mut changed|{
|
||||
for id in &mut changed.node_dep{
|
||||
*id += #sum_idents;
|
||||
}
|
||||
for id in &mut changed.parent_dep{
|
||||
*id += #sum_idents;
|
||||
}
|
||||
changed
|
||||
})
|
||||
}
|
||||
)*
|
||||
_ => panic!("{:?} not in {}", ty, #type_name_str),
|
||||
}
|
||||
}
|
||||
|
@ -129,13 +211,32 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||
ty: dioxus_native_core::state::MemberId,
|
||||
node: &'a dioxus_core::VNode<'a>,
|
||||
vdom: &'a dioxus_core::VirtualDom,
|
||||
children: &[&Self],
|
||||
children: &Vec<&Self>,
|
||||
ctx: &anymap::AnyMap,
|
||||
) -> Option<dioxus_native_core::state::ChildStatesChanged>{
|
||||
use dioxus_native_core::state::ChildDepState as _;
|
||||
match ty.0{
|
||||
#(
|
||||
#child_ids => {#child_dep_state_fields},
|
||||
#child_ids => #child_dep_state_fields,
|
||||
)*
|
||||
#(
|
||||
#child_state_ranges => {
|
||||
self.#child_state_idents.update_child_dep_state(
|
||||
ty - #sum_idents,
|
||||
node,
|
||||
vdom,
|
||||
&children.iter().map(|p| &p.#child_state_idents).collect(),
|
||||
ctx,
|
||||
).map(|mut changed|{
|
||||
for id in &mut changed.node_dep{
|
||||
*id += #sum_idents;
|
||||
}
|
||||
for id in &mut changed.child_dep{
|
||||
*id += #sum_idents;
|
||||
}
|
||||
changed
|
||||
})
|
||||
}
|
||||
)*
|
||||
_ => panic!("{:?} not in {}", ty, #type_name_str),
|
||||
}
|
||||
|
@ -146,6 +247,9 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||
#(if #child_types::NODE_MASK.overlaps(mask) {
|
||||
dep_types.push(dioxus_native_core::state::MemberId(#child_ids_clone));
|
||||
})*
|
||||
#(
|
||||
dep_types.extend(self.#child_state_idents.child_dep_types(mask).into_iter().map(|id| id + #sum_idents));
|
||||
)*
|
||||
dep_types
|
||||
}
|
||||
|
||||
|
@ -154,6 +258,9 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||
#(if #parent_types::NODE_MASK.overlaps(mask) {
|
||||
dep_types.push(dioxus_native_core::state::MemberId(#parent_ids_clone));
|
||||
})*
|
||||
#(
|
||||
dep_types.extend(self.#child_state_idents.parent_dep_types(mask).into_iter().map(|id| id + #sum_idents));
|
||||
)*
|
||||
dep_types
|
||||
}
|
||||
|
||||
|
@ -162,6 +269,9 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
|
|||
#(if #node_types::NODE_MASK.overlaps(mask) {
|
||||
dep_types.push(dioxus_native_core::state::MemberId(#node_ids_clone));
|
||||
})*
|
||||
#(
|
||||
dep_types.extend(self.#child_state_idents.node_dep_types(mask).into_iter().map(|id| id + #sum_idents));
|
||||
)*
|
||||
dep_types
|
||||
}
|
||||
}
|
||||
|
@ -186,6 +296,7 @@ impl Struct {
|
|||
|
||||
struct StateStruct<'a> {
|
||||
state_members: Vec<StateMember<'a>>,
|
||||
child_states: Vec<&'a Member>,
|
||||
}
|
||||
|
||||
impl<'a> StateStruct<'a> {
|
||||
|
@ -203,6 +314,20 @@ impl<'a> StateStruct<'a> {
|
|||
}
|
||||
});
|
||||
|
||||
let child_states = strct
|
||||
.members
|
||||
.iter()
|
||||
.zip(fields.iter())
|
||||
.filter(|(_, f)| {
|
||||
f.attrs.iter().any(|a| {
|
||||
a.path
|
||||
.get_ident()
|
||||
.filter(|i| i.to_string().as_str() == "state")
|
||||
.is_some()
|
||||
})
|
||||
})
|
||||
.map(|(m, _)| m);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct DepNode<'a> {
|
||||
state_mem: StateMember<'a>,
|
||||
|
@ -350,7 +475,10 @@ impl<'a> StateStruct<'a> {
|
|||
.flat_map(|r| r.flatten().into_iter())
|
||||
.collect();
|
||||
|
||||
Ok(Self { state_members })
|
||||
Ok(Self {
|
||||
state_members,
|
||||
child_states: child_states.collect(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -484,23 +612,23 @@ impl<'a> StateMember<'a> {
|
|||
DepKind::Node => {
|
||||
quote! {
|
||||
dioxus_native_core::state::NodeStatesChanged{
|
||||
node_dep: &[#(dioxus_native_core::state::MemberId(#node_dep), )*],
|
||||
node_dep: vec![#(dioxus_native_core::state::MemberId(#node_dep), )*],
|
||||
}
|
||||
}
|
||||
}
|
||||
DepKind::Child => {
|
||||
quote! {
|
||||
dioxus_native_core::state::ChildStatesChanged{
|
||||
node_dep: &[#(dioxus_native_core::state::MemberId(#node_dep), )*],
|
||||
child_dep: &[#(dioxus_native_core::state::MemberId(#child_dep), )*],
|
||||
node_dep: vec![#(dioxus_native_core::state::MemberId(#node_dep), )*],
|
||||
child_dep: vec![#(dioxus_native_core::state::MemberId(#child_dep), )*],
|
||||
}
|
||||
}
|
||||
}
|
||||
DepKind::Parent => {
|
||||
quote! {
|
||||
dioxus_native_core::state::ParentStatesChanged{
|
||||
node_dep: &[#(dioxus_native_core::state::MemberId(#node_dep), )*],
|
||||
parent_dep: &[#(dioxus_native_core::state::MemberId(#parent_dep), )*],
|
||||
node_dep: vec![#(dioxus_native_core::state::MemberId(#node_dep), )*],
|
||||
parent_dep: vec![#(dioxus_native_core::state::MemberId(#parent_dep), )*],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -515,7 +643,6 @@ impl<'a> StateMember<'a> {
|
|||
match self.dep_kind {
|
||||
DepKind::Node => {
|
||||
quote!({
|
||||
// println!("node: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
|
||||
if self.#ident.reduce(#node_view, &self.#dep_ident, #get_ctx){
|
||||
Some(#states_changed)
|
||||
} else{
|
||||
|
@ -525,7 +652,6 @@ impl<'a> StateMember<'a> {
|
|||
}
|
||||
DepKind::Child => {
|
||||
quote!({
|
||||
// println!("child: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
|
||||
if self.#ident.reduce(#node_view, children.iter().map(|s| &s.#dep_ident), #get_ctx){
|
||||
Some(#states_changed)
|
||||
} else{
|
||||
|
@ -535,7 +661,6 @@ impl<'a> StateMember<'a> {
|
|||
}
|
||||
DepKind::Parent => {
|
||||
quote!({
|
||||
// println!("parent: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
|
||||
if self.#ident.reduce(#node_view, parent.as_ref().map(|p| &p.#dep_ident), #get_ctx){
|
||||
Some(#states_changed)
|
||||
} else{
|
||||
|
@ -548,7 +673,6 @@ impl<'a> StateMember<'a> {
|
|||
match self.dep_kind {
|
||||
DepKind::Node => {
|
||||
quote!({
|
||||
// println!("node: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
|
||||
if self.#ident.reduce(#node_view, &(), #get_ctx){
|
||||
Some(#states_changed)
|
||||
} else{
|
||||
|
@ -558,7 +682,6 @@ impl<'a> StateMember<'a> {
|
|||
}
|
||||
DepKind::Child => {
|
||||
quote!({
|
||||
// println!("child: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
|
||||
if self.#ident.reduce(#node_view, std::iter::empty(), #get_ctx){
|
||||
Some(#states_changed)
|
||||
} else{
|
||||
|
@ -568,7 +691,6 @@ impl<'a> StateMember<'a> {
|
|||
}
|
||||
DepKind::Parent => {
|
||||
quote!({
|
||||
println!("parent: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
|
||||
if self.#ident.reduce(#node_view, Some(&()), #get_ctx){
|
||||
Some(#states_changed)
|
||||
} else{
|
||||
|
|
|
@ -8,12 +8,36 @@ use dioxus_native_core::real_dom::*;
|
|||
use dioxus_native_core::state::{ChildDepState, NodeDepState, ParentDepState, State};
|
||||
use dioxus_native_core_macro::State;
|
||||
|
||||
#[derive(Debug, Clone, Default, State)]
|
||||
struct CallCounterStatePart1 {
|
||||
#[child_dep_state(child_counter)]
|
||||
child_counter: ChildDepCallCounter,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, State)]
|
||||
struct CallCounterStatePart2 {
|
||||
#[parent_dep_state(parent_counter)]
|
||||
parent_counter: ParentDepCallCounter,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, State)]
|
||||
struct CallCounterStatePart3 {
|
||||
#[node_dep_state()]
|
||||
node_counter: NodeDepCallCounter,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, State)]
|
||||
struct CallCounterState {
|
||||
#[child_dep_state(child_counter)]
|
||||
child_counter: ChildDepCallCounter,
|
||||
#[state]
|
||||
part2: CallCounterStatePart2,
|
||||
#[parent_dep_state(parent_counter)]
|
||||
parent_counter: ParentDepCallCounter,
|
||||
#[state]
|
||||
part1: CallCounterStatePart1,
|
||||
#[state]
|
||||
part3: CallCounterStatePart3,
|
||||
#[node_dep_state()]
|
||||
node_counter: NodeDepCallCounter,
|
||||
}
|
||||
|
@ -261,8 +285,11 @@ fn state_reduce_initally_called_minimally() {
|
|||
let _to_rerender = dom.update_state(&vdom, nodes_updated, AnyMap::new());
|
||||
|
||||
dom.traverse_depth_first(|n| {
|
||||
assert_eq!(n.state.part1.child_counter.0, 1);
|
||||
assert_eq!(n.state.child_counter.0, 1);
|
||||
assert_eq!(n.state.part2.parent_counter.0, 1);
|
||||
assert_eq!(n.state.parent_counter.0, 1);
|
||||
assert_eq!(n.state.part3.node_counter.0, 1);
|
||||
assert_eq!(n.state.node_counter.0, 1);
|
||||
});
|
||||
}
|
||||
|
@ -329,6 +356,7 @@ fn state_reduce_parent_called_minimally_on_update() {
|
|||
let _to_rerender = dom.update_state(&vdom, nodes_updated, AnyMap::new());
|
||||
|
||||
dom.traverse_depth_first(|n| {
|
||||
assert_eq!(n.state.part2.parent_counter.0, 2);
|
||||
assert_eq!(n.state.parent_counter.0, 2);
|
||||
});
|
||||
}
|
||||
|
@ -398,6 +426,10 @@ fn state_reduce_child_called_minimally_on_update() {
|
|||
|
||||
dom.traverse_depth_first(|n| {
|
||||
println!("{:?}", n);
|
||||
assert_eq!(
|
||||
n.state.part1.child_counter.0,
|
||||
if n.id.0 > 4 { 1 } else { 2 }
|
||||
);
|
||||
assert_eq!(n.state.child_counter.0, if n.id.0 > 4 { 1 } else { 2 });
|
||||
});
|
||||
}
|
||||
|
@ -487,3 +519,15 @@ fn dependancies_order_independant() {
|
|||
assert_eq!(&n.state.c, &c);
|
||||
});
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, State)]
|
||||
struct DependanciesStateTest {
|
||||
#[node_dep_state(c)]
|
||||
b: BDepCallCounter,
|
||||
#[node_dep_state()]
|
||||
c: CDepCallCounter,
|
||||
#[node_dep_state(b)]
|
||||
a: ADepCallCounter,
|
||||
#[state]
|
||||
child: UnorderedDependanciesState,
|
||||
}
|
||||
|
|
|
@ -308,7 +308,7 @@ impl<S: State> RealDom<S> {
|
|||
node.state.update_node_dep_state(id, vnode, vdom, &ctx)
|
||||
{
|
||||
debug_assert!(members_effected.node_dep.iter().all(|i| i >= &id));
|
||||
for m in members_effected.node_dep {
|
||||
for m in &members_effected.node_dep {
|
||||
if let Err(idx) = ids.binary_search(m) {
|
||||
ids.insert(idx, *m);
|
||||
}
|
||||
|
@ -348,12 +348,12 @@ impl<S: State> RealDom<S> {
|
|||
{
|
||||
debug_assert!(members_effected.node_dep.iter().all(|i| i >= &id));
|
||||
for m in members_effected.node_dep {
|
||||
if let Err(idx) = ids.binary_search(m) {
|
||||
ids.insert(idx, *m);
|
||||
if let Err(idx) = ids.binary_search(&m) {
|
||||
ids.insert(idx, m);
|
||||
}
|
||||
}
|
||||
for m in members_effected.child_dep {
|
||||
changed.push(*m);
|
||||
changed.push(m);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
|
@ -416,12 +416,12 @@ impl<S: State> RealDom<S> {
|
|||
{
|
||||
debug_assert!(members_effected.node_dep.iter().all(|i| i >= &id));
|
||||
for m in members_effected.node_dep {
|
||||
if let Err(idx) = ids.binary_search(m) {
|
||||
ids.insert(idx, *m);
|
||||
if let Err(idx) = ids.binary_search(&m) {
|
||||
ids.insert(idx, m);
|
||||
}
|
||||
}
|
||||
for m in members_effected.parent_dep {
|
||||
changed.push(*m);
|
||||
changed.push(m);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
use std::{cmp::Ordering, fmt::Debug};
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
fmt::Debug,
|
||||
ops::{Add, AddAssign, Sub, SubAssign},
|
||||
};
|
||||
|
||||
use anymap::AnyMap;
|
||||
use dioxus_core::VNode;
|
||||
|
@ -81,22 +85,24 @@ pub trait NodeDepState {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ChildStatesChanged {
|
||||
pub node_dep: &'static [MemberId],
|
||||
pub child_dep: &'static [MemberId],
|
||||
pub node_dep: Vec<MemberId>,
|
||||
pub child_dep: Vec<MemberId>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParentStatesChanged {
|
||||
pub node_dep: &'static [MemberId],
|
||||
pub parent_dep: &'static [MemberId],
|
||||
pub node_dep: Vec<MemberId>,
|
||||
pub parent_dep: Vec<MemberId>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NodeStatesChanged {
|
||||
pub node_dep: &'static [MemberId],
|
||||
pub node_dep: Vec<MemberId>,
|
||||
}
|
||||
|
||||
pub trait State: Default + Clone {
|
||||
const SIZE: usize;
|
||||
|
||||
fn update_node_dep_state<'a>(
|
||||
&'a mut self,
|
||||
ty: MemberId,
|
||||
|
@ -123,7 +129,7 @@ pub trait State: Default + Clone {
|
|||
ty: MemberId,
|
||||
node: &'a VNode<'a>,
|
||||
vdom: &'a dioxus_core::VirtualDom,
|
||||
children: &[&Self],
|
||||
children: &Vec<&Self>,
|
||||
ctx: &AnyMap,
|
||||
) -> Option<ChildStatesChanged>;
|
||||
/// This must be a valid resolution order. (no nodes updated before a state they rely on)
|
||||
|
@ -165,3 +171,29 @@ impl NodeDepState for () {
|
|||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct MemberId(pub usize);
|
||||
|
||||
impl Sub<usize> for MemberId {
|
||||
type Output = MemberId;
|
||||
fn sub(self, rhs: usize) -> Self::Output {
|
||||
MemberId(self.0 - rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<usize> for MemberId {
|
||||
type Output = MemberId;
|
||||
fn add(self, rhs: usize) -> Self::Output {
|
||||
MemberId(self.0 + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl SubAssign<usize> for MemberId {
|
||||
fn sub_assign(&mut self, rhs: usize) {
|
||||
*self = *self - rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<usize> for MemberId {
|
||||
fn add_assign(&mut self, rhs: usize) {
|
||||
*self = *self + rhs;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue