work in progress reactivity

This commit is contained in:
Daniel Bulant 2023-10-31 16:24:27 +01:00
parent c83bd506ab
commit 527af977e5
9 changed files with 240 additions and 78 deletions

View file

@ -1,11 +1,13 @@
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use mangui::{SharedNode, nodes::{layout::Layout, Style}, taffy::prelude::Size}; use mangui::{SharedNode, nodes::{layout::Layout, Style}, taffy::prelude::Size};
use rusalka::{component::Component, nodes::{primitives::{Rectangle, RectangleAttributes}, insert, detach}, SharedComponent}; use rusalka::{component::Component, nodes::{primitives::{Rectangle, RectangleAttributes}, insert, detach}, SharedComponent, WeakSharedComponent, invalidator::Invalidator};
pub struct DemoComponent { pub struct DemoComponent {
rect: SharedComponent<Rectangle>, rect: SharedComponent<Rectangle>,
attrs: DemoComponentAttributes, attrs: DemoComponentAttributes,
layout: Arc<RwLock<Layout>> layout: Arc<RwLock<Layout>>,
selfref: WeakSharedComponent<Self>,
test: Arc<Mutex<Invalidator<bool>>>
} }
#[derive(Default)] #[derive(Default)]
@ -23,14 +25,15 @@ impl From<DemoComponentAttributes> for PartialDemoComponentAttributes {
impl Component for DemoComponent { impl Component for DemoComponent {
type ComponentAttrs = DemoComponentAttributes; type ComponentAttrs = DemoComponentAttributes;
type PartialComponentAttrs = PartialDemoComponentAttributes; type PartialComponentAttrs = PartialDemoComponentAttributes;
fn new(attrs: Self::ComponentAttrs) -> Self { fn new(attrs: Self::ComponentAttrs, selfref: WeakSharedComponent<Self>) -> Self {
Self { let test = Arc::new(Mutex::new(Invalidator::new(false)));
rect: Arc::new(Mutex::new(Rectangle::new(RectangleAttributes { ..Default::default() }))), let self_ = Self {
rect: Arc::new_cyclic(|selfref| Mutex::new(Rectangle::new(RectangleAttributes { ..Default::default() }, selfref.clone()))),
layout: Arc::new(RwLock::new(Layout { layout: Arc::new(RwLock::new(Layout {
style: Style { style: Style {
layout: mangui::nodes::TaffyStyle { layout: mangui::nodes::TaffyStyle {
min_size: Size { min_size: Size {
width: mangui::taffy::style::Dimension::Points(50.), width: mangui::taffy::style::Dimension::Points( if **test.lock().unwrap() { 50. } else { 100. }),
height: mangui::taffy::style::Dimension::Points(100.) height: mangui::taffy::style::Dimension::Points(100.)
}, },
..Default::default() ..Default::default()
@ -40,7 +43,26 @@ impl Component for DemoComponent {
..Default::default() ..Default::default()
})), })),
attrs, attrs,
} selfref,
test
};
let selfref = self_.selfref.clone();
self_.layout.write().unwrap().events.add_handler(Box::new(move |event| {
let selfref = selfref.upgrade().unwrap();
let self_ = selfref.lock().unwrap();
let test = &self_.test;
let attrs = &self_.attrs;
match event.event {
mangui::events::InnerEvent::MouseDown(_) => {
**test.lock().unwrap() = true;
},
mangui::events::InnerEvent::MouseUp(_) => {
**test.lock().unwrap() = false;
},
_ => {}
}
}));
self_
} }
fn set(&mut self, _attrs: Self::PartialComponentAttrs) { } fn set(&mut self, _attrs: Self::PartialComponentAttrs) { }

View file

@ -6,18 +6,32 @@ use rusalka::nodes::primitives::{Rectangle, RectangleAttributes};
make_component!( make_component!(
ComponentDemo, ComponentDemo,
Logic { MainLogic {
let radius = attrs.radius; let radius = attrs.radius;
} }
Attributes { Attributes {
radius: f32 radius: f32
} }
Variables {
test: bool = false
}
Component { Component {
@layout { @layout {
@Rectangle { @Rectangle {
radius, radius: if $test { radius } else { 0. },
..Default::default() ..Default::default()
} }
$|event| {
match event.event {
mangui::events::InnerEvent::MouseDown(_) => {
$test = true;
},
mangui::events::InnerEvent::MouseUp(_) => {
$test = false;
},
_ => {}
}
}
..Default::default() ..Default::default()
} }
} }

View file

@ -1,6 +1,6 @@
use std::sync::{RwLock, Arc, mpsc}; use std::sync::{RwLock, Arc, mpsc};
use mangui::{self, nodes::{layout::Layout, self, Style, TaffyStyle}, taffy::{self, prelude::Size, style::Dimension}, femtovg::{Paint, Color}, SharedNode, MainEntry}; use mangui::{self, nodes::{layout::Layout, self, Style, TaffyStyle}, taffy::{self, prelude::Size, style::Dimension}, femtovg::{Paint, Color}, SharedNode, MainEntry, events::NodeEvent};
mod component_demo; mod component_demo;
mod component_demo_syntax; mod component_demo_syntax;
@ -30,7 +30,8 @@ fn main() {
})); }));
root.children.push(right_node.clone()); root.children.push(right_node.clone());
right_node.clone().write().unwrap().events.add_handler(Box::new(move |event| { right_node.clone().write().unwrap().events.add_handler(Box::new(move |event| {
match event.event { let NodeEvent { target, path, event } = event;
match event {
mangui::events::InnerEvent::MouseDown(_) => { mangui::events::InnerEvent::MouseDown(_) => {
right_node.write().unwrap().fill = Paint::color(Color::rgb(255, 0, 255)); right_node.write().unwrap().fill = Paint::color(Color::rgb(255, 0, 255));
}, },

View file

@ -8,6 +8,11 @@ struct Attribute {
type_: TokenStream type_: TokenStream
} }
#[derive(Debug)]
struct EventListener {
callback: TokenStream
}
#[derive(Debug)] #[derive(Debug)]
enum ComponentType { enum ComponentType {
RealComponent, RealComponent,
@ -19,7 +24,8 @@ struct ComponentUsed {
name: Ident, name: Ident,
contents: TokenStream, contents: TokenStream,
parent: Option<usize>, parent: Option<usize>,
component_type: ComponentType component_type: ComponentType,
event_listeners: Vec<EventListener>
} }
#[proc_macro] #[proc_macro]
@ -41,7 +47,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
let mut main_logic = Vec::new(); let mut main_logic = Vec::new();
// let mut reactive_variables = Vec::new(); let mut reactive_variables = Vec::new();
let mut components_used: Vec<ComponentUsed> = Vec::new(); let mut components_used: Vec<ComponentUsed> = Vec::new();
@ -52,7 +58,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
let ident = ident.to_string(); let ident = ident.to_string();
match ident.as_str() { match ident.as_str() {
"Logic" | "Component" | "Attributes" => {}, "MainLogic" | "Component" | "Attributes" | "Variables" => {},
_ => panic!("Unknown identifier: {:?}", ident) _ => panic!("Unknown identifier: {:?}", ident)
} }
}, },
@ -60,7 +66,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
match &last_identifier { match &last_identifier {
Some(ident) => { Some(ident) => {
match ident.as_str() { match ident.as_str() {
"Attributes" => { "Attributes" | "Variables" => {
// A struct-like definition of attributes // A struct-like definition of attributes
// Example syntax: // Example syntax:
// Attributes { // we're here // Attributes { // we're here
@ -120,6 +126,12 @@ pub fn make_component(item: TokenStream) -> TokenStream {
} }
} }
let array = if ident.as_str() == "Variables" {
&mut reactive_variables
} else {
&mut attributes
};
if last_was_set { if last_was_set {
let mut default = TokenStream::new(); let mut default = TokenStream::new();
@ -141,13 +153,13 @@ pub fn make_component(item: TokenStream) -> TokenStream {
} }
} }
attributes.push(Attribute { array.push(Attribute {
name, name,
default: Some(default), default: Some(default),
type_ type_
}); });
} else { } else {
attributes.push(Attribute { array.push(Attribute {
name, name,
default: None, default: None,
type_ type_
@ -155,7 +167,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
} }
} }
}, },
"Logic" => { "MainLogic" => {
main_logic.push(group.stream()); main_logic.push(group.stream());
}, },
"Component" => { "Component" => {
@ -253,6 +265,19 @@ pub fn make_component(item: TokenStream) -> TokenStream {
i+=1; i+=1;
} }
for variable in &reactive_variables {
component_struct_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
component_struct_stream.extend(TokenStream::from(quote!(:)));
component_struct_stream.extend(TokenStream::from(quote!(Arc<Mutex<Invalidator<)));
component_struct_stream.extend(variable.type_.clone());
component_struct_stream.extend(TokenStream::from(quote!(>>>)));
component_struct_stream.extend(TokenStream::from(quote!(,)));
}
// selfref
component_struct_stream.extend(TokenStream::from(quote!(selfref: rusalka::WeakSharedComponent<Self>,)));
// Attributes struct // Attributes struct
let attributes_ident = Ident::new(&format!("{str_name}Attributes"), Span::call_site()); let attributes_ident = Ident::new(&format!("{str_name}Attributes"), Span::call_site());
@ -355,10 +380,29 @@ pub fn make_component(item: TokenStream) -> TokenStream {
// fn new // fn new
component_impl_stream.extend(TokenStream::from(quote!(fn new(attrs: Self::ComponentAttrs) -> Self))); component_impl_stream.extend(TokenStream::from(quote!(fn new(attrs: Self::ComponentAttrs, selfref: rusalka::WeakSharedComponent<Self>) -> Self)));
let mut new_stream = TokenStream::new(); let mut new_stream = TokenStream::new();
for variable in &reactive_variables {
new_stream.extend(TokenStream::from(quote!(let)));
new_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
new_stream.extend(TokenStream::from(quote!(:)));
// new_stream.extend(TokenStream::from(quote!(Arc::new(Mutex::new(Invalidator::new)))));
let mut invalidator = TokenStream::from(quote!(rusalka::invalidator::Invalidator::new));
let mut invalidator_inner = TokenStream::new();
if let Some(def) = &variable.default {
invalidator_inner.extend(def.clone());
} else {
invalidator_inner.extend(TokenStream::from(quote!(Default::default())));
}
invalidator.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Parenthesis, invalidator_inner))));
new_stream.extend(wrap_in_arc_mutex(invalidator));
new_stream.extend(TokenStream::from(quote!(;)));
}
new_stream.extend(main_logic); new_stream.extend(main_logic);
new_stream.extend(TokenStream::from(quote!(Self))); new_stream.extend(TokenStream::from(quote!(Self)));
@ -369,7 +413,6 @@ pub fn make_component(item: TokenStream) -> TokenStream {
for component in &components_used { for component in &components_used {
let ident = Ident::new(&format!("comp{}", i), Span::call_site()); let ident = Ident::new(&format!("comp{}", i), Span::call_site());
let component_name = component.name.clone(); let component_name = component.name.clone();
dbg!(&component_name);
new_returnvalue_stream.extend(Some(TokenTree::Ident(ident))); new_returnvalue_stream.extend(Some(TokenTree::Ident(ident)));
new_returnvalue_stream.extend(TokenStream::from(quote!(:))); new_returnvalue_stream.extend(TokenStream::from(quote!(:)));
@ -395,11 +438,13 @@ pub fn make_component(item: TokenStream) -> TokenStream {
component_new_stream.extend(Some(TokenTree::Group(components_attributes_group))); component_new_stream.extend(Some(TokenTree::Group(components_attributes_group)));
component_new_stream.extend(TokenStream::from(quote!(, cselfref.clone())));
let component_new_group = Group::new(proc_macro::Delimiter::Parenthesis, component_new_stream); let component_new_group = Group::new(proc_macro::Delimiter::Parenthesis, component_new_stream);
component_stream.extend(Some(TokenTree::Group(component_new_group))); component_stream.extend(Some(TokenTree::Group(component_new_group)));
new_returnvalue_stream.extend(wrap_in_arcmutex(component_stream)); new_returnvalue_stream.extend(wrap_in_arcmutex_cyclic(component_stream));
}, },
ComponentType::Node => { ComponentType::Node => {
let node_group = Group::new(proc_macro::Delimiter::Brace, component.contents.clone()); let node_group = Group::new(proc_macro::Delimiter::Brace, component.contents.clone());
@ -412,7 +457,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
i+=1; i+=1;
} }
new_returnvalue_stream.extend(TokenStream::from(quote!(attrs))); new_returnvalue_stream.extend(TokenStream::from(quote!(attrs, selfref)));
let new_returnvalue_group = Group::new(proc_macro::Delimiter::Brace, new_returnvalue_stream); let new_returnvalue_group = Group::new(proc_macro::Delimiter::Brace, new_returnvalue_stream);
new_stream.extend(Some(TokenTree::Group(new_returnvalue_group))); new_stream.extend(Some(TokenTree::Group(new_returnvalue_group)));
@ -483,11 +528,10 @@ pub fn make_component(item: TokenStream) -> TokenStream {
match component.component_type { match component.component_type {
ComponentType::RealComponent => { ComponentType::RealComponent => {
let mut component_stream = TokenStream::new(); // mount
mount_stream.extend(TokenStream::from(quote!(self.)));
component_stream.extend(TokenStream::from(quote!(self.))); mount_stream.extend(Some(TokenTree::Ident(ident)));
component_stream.extend(Some(TokenTree::Ident(ident))); mount_stream.extend(TokenStream::from(quote!(.lock().unwrap().mount)));
component_stream.extend(TokenStream::from(quote!(.lock().unwrap().mount)));
let mut component_mount_stream = TokenStream::new(); let mut component_mount_stream = TokenStream::new();
@ -514,9 +558,8 @@ pub fn make_component(item: TokenStream) -> TokenStream {
let component_mount_group = Group::new(proc_macro::Delimiter::Parenthesis, component_mount_stream); let component_mount_group = Group::new(proc_macro::Delimiter::Parenthesis, component_mount_stream);
component_stream.extend(Some(TokenTree::Group(component_mount_group))); mount_stream.extend(Some(TokenTree::Group(component_mount_group)));
mount_stream.extend(component_stream);
mount_stream.extend(TokenStream::from(quote!(;))); mount_stream.extend(TokenStream::from(quote!(;)));
}, },
ComponentType::Node => { ComponentType::Node => {
@ -605,10 +648,13 @@ pub fn make_component(item: TokenStream) -> TokenStream {
output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, component_impl_stream)))); output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, component_impl_stream))));
// dbg!(&output); // dbg!(&output);
dbg!(attributes); dbg!(attributes);
dbg!(reactive_variables);
println!("{}", output.to_string()); println!("{}", output.to_string());
println!(); println!();
@ -616,12 +662,12 @@ pub fn make_component(item: TokenStream) -> TokenStream {
output output
} }
fn wrap_in_arcmutex(stream: TokenStream) -> TokenStream { fn wrap_in_arc_mutex(stream: TokenStream) -> TokenStream {
let mut output = TokenStream::new(); let mut output = TokenStream::new();
output.extend(TokenStream::from(quote!(std::sync::Arc::new))); output.extend(TokenStream::from(quote!(std::sync::Arc::new)));
let mut mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream); let mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream);
let mut mutex_stream = TokenStream::new(); let mut mutex_stream = TokenStream::new();
@ -636,20 +682,42 @@ fn wrap_in_arcmutex(stream: TokenStream) -> TokenStream {
output output
} }
fn wrap_in_arcmutex_cyclic(stream: TokenStream) -> TokenStream {
let mut output = TokenStream::new();
output.extend(TokenStream::from(quote!(std::sync::Arc::new_cyclic)));
let mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream);
let mut mutex_stream = TokenStream::new();
mutex_stream.extend(TokenStream::from(quote!(|cselfref|)));
mutex_stream.extend(TokenStream::from(quote!(std::sync::Mutex::new)));
mutex_stream.extend(Some(TokenTree::Group(mutex_group)));
let arc_group = Group::new(proc_macro::Delimiter::Parenthesis, mutex_stream);
output.extend(Some(TokenTree::Group(arc_group)));
output
}
fn wrap_in_arcrwlock(stream: TokenStream) -> TokenStream { fn wrap_in_arcrwlock(stream: TokenStream) -> TokenStream {
let mut output = TokenStream::new(); let mut output = TokenStream::new();
output.extend(TokenStream::from(quote!(std::sync::Arc::new))); output.extend(TokenStream::from(quote!(std::sync::Arc::new)));
let mut mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream); let mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream);
let mut mutex_stream = TokenStream::new(); let mut rwlock_stream = TokenStream::new();
mutex_stream.extend(TokenStream::from(quote!(std::sync::RwLock::new))); rwlock_stream.extend(TokenStream::from(quote!(std::sync::RwLock::new)));
mutex_stream.extend(Some(TokenTree::Group(mutex_group))); rwlock_stream.extend(Some(TokenTree::Group(mutex_group)));
let arc_group = Group::new(proc_macro::Delimiter::Parenthesis, mutex_stream); let arc_group = Group::new(proc_macro::Delimiter::Parenthesis, rwlock_stream);
output.extend(Some(TokenTree::Group(arc_group))); output.extend(Some(TokenTree::Group(arc_group)));
@ -681,47 +749,64 @@ fn parse_components(name: Ident, group: Group, next: usize, parent: Option<usize
} else { name }, } else { name },
contents: self_stream.clone(), contents: self_stream.clone(),
parent, parent,
component_type: if name_starts_lowercase { ComponentType::Node } else { ComponentType::RealComponent } component_type: if name_starts_lowercase { ComponentType::Node } else { ComponentType::RealComponent },
event_listeners: Vec::new()
}; };
components_found.push(this_component); components_found.push(this_component);
while let Some(token) = group.next() { while let Some(token) = group.next() {
match token { match token {
TokenTree::Punct(punct) => { TokenTree::Punct(punct) if punct.as_char() == '@' => {
if punct.as_char() == '@' { let ident = group.next().unwrap();
let ident = group.next().unwrap(); let ident = match ident {
let ident = match ident { TokenTree::Ident(ident) => ident,
TokenTree::Ident(ident) => ident, _ => panic!("Expected ident after @")
_ => panic!("Expected ident after @") };
};
let group = group.next().unwrap(); let group = group.next().unwrap();
let group = match group { let group = match group {
TokenTree::Group(group) => group, TokenTree::Group(group) => group,
_ => panic!("Expected group after ident") _ => panic!("Expected group after ident")
}; };
let components = parse_components(ident, group, next + components_found.len() + 1, Some(next)); let components = parse_components(ident, group, next + components_found.len() + 1, Some(next));
components_found.extend(components); components_found.extend(components);
} else { },
self_stream.extend(Some(TokenTree::Punct(punct))); TokenTree::Punct(punct) if punct.as_char() == '$' => {
while let Some(token) = group.next() { // event handler
match token { let fn_start = group.next().unwrap();
TokenTree::Punct(punct) => { match fn_start {
if punct.as_char() == ',' { TokenTree::Punct(punct) if punct.as_char() == '|' => {},
break; _ => panic!("Expected | after $ (event handlers). Move is added automatically")
} else {
self_stream.extend(Some(TokenTree::Punct(punct)));
}
},
_ => {
self_stream.extend(Some(token));
}
}
}
} }
let fn_param = group.next().unwrap();
let fn_param = match fn_param {
TokenTree::Ident(ident) => ident,
_ => panic!("Expected ident after |")
};
let fn_end = group.next().unwrap();
match fn_end {
TokenTree::Punct(punct) if punct.as_char() == '|' => {},
_ => panic!("Expected | after fn param")
}
let fn_group = group.next().unwrap();
let fn_group = match fn_group {
TokenTree::Group(group) => group,
_ => panic!("Expected group after |param|")
};
let mut callback_stream = TokenStream::from(quote!(move |#));
callback_stream.extend(Some(TokenTree::Ident(fn_param)));
callback_stream.extend(TokenStream::from(quote!(|)));
callback_stream.extend(Some(TokenTree::Group(fn_group)));
let this_component = components_found.get_mut(next).unwrap();
this_component.event_listeners.push(EventListener {
callback: callback_stream
});
}, },
any => { any => {
// skip until next ',', writing to self_stream // skip until next ',', writing to self_stream

View file

@ -1,16 +1,19 @@
use mangui::{SharedNode, nodes::Node}; use mangui::{SharedNode, nodes::Node};
use crate::WeakSharedComponent;
/// A rusalka component /// A rusalka component
pub trait Component { pub trait Component {
type ComponentAttrs: Default; type ComponentAttrs: Default;
type PartialComponentAttrs: Default + From<Self::ComponentAttrs>; type PartialComponentAttrs: Default + From<Self::ComponentAttrs>;
const UPDATE_LENGTH : usize = 0; const UPDATE_LENGTH : usize = 0;
fn new(attr: Self::ComponentAttrs) -> Self; fn new(attr: Self::ComponentAttrs, selfref: WeakSharedComponent<Self>) -> Self;
fn get(&self) -> &Self::ComponentAttrs; fn get(&self) -> &Self::ComponentAttrs;
fn set(&mut self, attr: Self::PartialComponentAttrs); fn set(&mut self, attr: Self::PartialComponentAttrs);
fn mount(&self, parent: &SharedNode, before: Option<&SharedNode>); fn mount(&self, parent: &SharedNode, before: Option<&SharedNode>);
fn update(&self, bitmap: &[u32]); fn update(&self, bitmap: &[u32]);
fn unmount(&self); fn unmount(&self);
// fn set_selfref(&mut self, selfref: SharedComponent<Self>);
fn check_update(&self, bitmap: &[u32]) -> () { fn check_update(&self, bitmap: &[u32]) -> () {
if bitmap.len() != Self::UPDATE_LENGTH { if bitmap.len() != Self::UPDATE_LENGTH {

View file

@ -0,0 +1,36 @@
use std::ops::{Deref, DerefMut};
pub struct Invalidator<T> {
inner: T,
invalidated: bool
}
impl<T> Invalidator<T> {
pub fn new(inner: T) -> Self {
Self {
inner,
invalidated: false
}
}
pub fn reset(&mut self) {
self.invalidated = false;
}
pub fn invalidated(&self) -> bool {
self.invalidated
}
}
impl<T> Deref for Invalidator<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<T> DerefMut for Invalidator<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.invalidated = true;
&mut self.inner
}
}

View file

@ -5,6 +5,8 @@ use mangui::nodes::Node;
pub mod component; pub mod component;
pub mod nodes; pub mod nodes;
pub mod invalidator;
pub type SharedComponent<T: Component> = Arc<Mutex<T>>; pub type SharedComponent<T: Component> = Arc<Mutex<T>>;
pub type WeakSharedComponent<T: Component> = std::sync::Weak<Mutex<T>>;
pub type SharedNodeComponent<T: Node> = Arc<RwLock<T>>; pub type SharedNodeComponent<T: Node> = Arc<RwLock<T>>;

View file

@ -1,3 +0,0 @@
fn main() {
println!("Hello, world!");
}

View file

@ -4,13 +4,14 @@
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use mangui::{SharedNode, nodes::{primitives, Style}, taffy::prelude::Size, femtovg::{Paint, Color}}; use mangui::{SharedNode, nodes::{primitives, Style}, taffy::prelude::Size, femtovg::{Paint, Color}};
use crate::component::Component; use crate::{component::Component, SharedComponent, WeakSharedComponent};
use super::{insert, detach}; use super::{insert, detach};
pub struct Rectangle { pub struct Rectangle {
node: Arc<RwLock<primitives::Rectangle>>, node: Arc<RwLock<primitives::Rectangle>>,
attrs: RectangleAttributes attrs: RectangleAttributes,
selfref: WeakSharedComponent<Self>
} }
#[derive(Default)] #[derive(Default)]
@ -36,7 +37,7 @@ impl Component for Rectangle {
type ComponentAttrs = RectangleAttributes; type ComponentAttrs = RectangleAttributes;
type PartialComponentAttrs = PartialRectangleAttributes; type PartialComponentAttrs = PartialRectangleAttributes;
const UPDATE_LENGTH : usize = 1; const UPDATE_LENGTH : usize = 1;
fn new(attrs: Self::ComponentAttrs) -> Self { fn new(attrs: Self::ComponentAttrs, selfref: WeakSharedComponent<Self>) -> Self {
Self { Self {
node: Arc::new(RwLock::new(primitives::Rectangle { node: Arc::new(RwLock::new(primitives::Rectangle {
style: Style { style: Style {
@ -53,7 +54,8 @@ impl Component for Rectangle {
radius: attrs.radius, radius: attrs.radius,
..Default::default() ..Default::default()
})), })),
attrs attrs,
selfref
} }
} }