mirror of
https://github.com/danbulant/mangui
synced 2026-05-24 12:21:54 +00:00
working reactivity in components
This commit is contained in:
parent
327a13147d
commit
1870d6e65e
4 changed files with 138 additions and 12 deletions
|
|
@ -2,7 +2,7 @@ use rusalka_macro::make_component;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use mangui::{SharedNode, nodes::Style, taffy::prelude::Size, femtovg::{Paint, Color}, nodes::layout::Layout};
|
use mangui::{SharedNode, nodes::Style, taffy::prelude::Size, femtovg::{Paint, Color}, nodes::layout::Layout};
|
||||||
|
|
||||||
use rusalka::nodes::primitives::{Rectangle, RectangleAttributes};
|
use rusalka::nodes::primitives::{Rectangle, RectangleAttributes, PartialRectangleAttributes};
|
||||||
|
|
||||||
make_component!(
|
make_component!(
|
||||||
ComponentDemo,
|
ComponentDemo,
|
||||||
|
|
@ -16,7 +16,7 @@ make_component!(
|
||||||
test_: bool = false
|
test_: bool = false
|
||||||
}
|
}
|
||||||
Reactive {
|
Reactive {
|
||||||
dbg!($test_);
|
// dbg!($test_);
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
@layout {
|
@layout {
|
||||||
|
|
@ -28,11 +28,9 @@ make_component!(
|
||||||
match event.event {
|
match event.event {
|
||||||
mangui::events::InnerEvent::MouseDown(_) => {
|
mangui::events::InnerEvent::MouseDown(_) => {
|
||||||
$test_ = true;
|
$test_ = true;
|
||||||
println!("Mouse down");
|
|
||||||
},
|
},
|
||||||
mangui::events::InnerEvent::MouseUp(_) => {
|
mangui::events::InnerEvent::MouseUp(_) => {
|
||||||
$test_ = false;
|
$test_ = false;
|
||||||
println!("Mouse up");
|
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,11 @@ fn main() {
|
||||||
}));
|
}));
|
||||||
let groot: SharedNode = Arc::new(RwLock::new(root));
|
let groot: SharedNode = Arc::new(RwLock::new(root));
|
||||||
|
|
||||||
let cdemo: Arc<Mutex<component_demo_syntax::ComponentDemo>> = Arc::new_cyclic(|cself| Mutex::new(component_demo_syntax::ComponentDemo::new(component_demo_syntax::ComponentDemoAttributes { radius: 10. }, cself.clone())));
|
let cdemo: Arc<Mutex<component_demo_syntax::ComponentDemo>> = Arc::new_cyclic(|cself|
|
||||||
|
Mutex::new(component_demo_syntax::ComponentDemo::new(component_demo_syntax::ComponentDemoAttributes {
|
||||||
|
radius: 15.
|
||||||
|
}, cself.clone()))
|
||||||
|
);
|
||||||
cdemo.lock().unwrap().mount(&groot, None);
|
cdemo.lock().unwrap().mount(&groot, None);
|
||||||
|
|
||||||
mangui::run_event_loop(MainEntry {
|
mangui::run_event_loop(MainEntry {
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,14 @@ struct ComponentUsed {
|
||||||
parent: Option<usize>,
|
parent: Option<usize>,
|
||||||
component_type: ComponentType,
|
component_type: ComponentType,
|
||||||
event_listeners: Vec<EventListener>,
|
event_listeners: Vec<EventListener>,
|
||||||
reactive_props: HashMap<Ident, ReactiveBlock>
|
reactive_props: HashMap<String, ReactiveBlock>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ReactiveBlock {
|
struct ReactiveBlock {
|
||||||
variables: Vec<Ident>,
|
variables: Vec<Ident>,
|
||||||
contents: TokenStream
|
contents: TokenStream,
|
||||||
|
prop_ident: Option<Ident>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
|
|
@ -202,7 +203,8 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
let (variables, contents) = replace_variables(group.stream());
|
let (variables, contents) = replace_variables(group.stream());
|
||||||
reactive_blocks.push(ReactiveBlock {
|
reactive_blocks.push(ReactiveBlock {
|
||||||
variables,
|
variables,
|
||||||
contents
|
contents,
|
||||||
|
prop_ident: None
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
"Component" => {
|
"Component" => {
|
||||||
|
|
@ -606,8 +608,8 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
set_stream_inner.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Bracket, to_update_stream))));
|
set_stream_inner.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Bracket, to_update_stream))));
|
||||||
|
|
||||||
set_stream_inner.extend(TokenStream::from(quote!(|= 1 <<)));
|
set_stream_inner.extend(TokenStream::from(quote!(|= )));
|
||||||
set_stream_inner.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(i % 32))));
|
set_stream_inner.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(1 << i % 32))));
|
||||||
|
|
||||||
set_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, set_stream_inner))));
|
set_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, set_stream_inner))));
|
||||||
|
|
||||||
|
|
@ -807,6 +809,87 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
update_stream.extend(Some(TokenTree::Group(inner_group)));
|
update_stream.extend(Some(TokenTree::Group(inner_group)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut component_index = 0;
|
||||||
|
'block: for component in &components_used {
|
||||||
|
for (prop, block) in &component.reactive_props {
|
||||||
|
let mut keys: Vec<u32> = vec![0; all_variables.len() / 32 + 1];
|
||||||
|
for variable in &block.variables {
|
||||||
|
let index = all_variables.iter().position(|x| x.name.to_string() == variable.to_string());
|
||||||
|
if let None = index {
|
||||||
|
eprintln!("Warning: variable {} not found in component {}", variable, name);
|
||||||
|
continue 'block;
|
||||||
|
}
|
||||||
|
let index = index.unwrap();
|
||||||
|
let array_offset = index / 32;
|
||||||
|
let num_offset = index % 32;
|
||||||
|
*keys.get_mut(array_offset).unwrap() |= 1 << num_offset;
|
||||||
|
}
|
||||||
|
update_stream.extend(TokenStream::from(quote!(if)));
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for key in keys {
|
||||||
|
if i > 0 {
|
||||||
|
update_stream.extend(TokenStream::from(quote!(||)));
|
||||||
|
}
|
||||||
|
update_stream.extend(TokenStream::from(quote!(bitmap)));
|
||||||
|
let mut ifgroup_stream = TokenStream::new();
|
||||||
|
// update_stream.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(key))));
|
||||||
|
ifgroup_stream.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(i))));
|
||||||
|
update_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Bracket, ifgroup_stream))));
|
||||||
|
update_stream.extend(TokenStream::from(quote!(&)));
|
||||||
|
update_stream.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(key))));
|
||||||
|
update_stream.extend(TokenStream::from(quote!(!= 0)));
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut inner_stream = TokenStream::new();
|
||||||
|
|
||||||
|
match component.component_type {
|
||||||
|
ComponentType::Node => {
|
||||||
|
inner_stream.extend(TokenStream::from(quote!(self.)));
|
||||||
|
inner_stream.extend(Some(TokenTree::Ident(Ident::new(&format!("comp{}", component_index), Span::call_site()))));
|
||||||
|
inner_stream.extend(TokenStream::from(quote!(.write().unwrap().)));
|
||||||
|
inner_stream.extend(Some(TokenTree::Ident(block.prop_ident.clone().unwrap())));
|
||||||
|
inner_stream.extend(TokenStream::from(quote!( = )));
|
||||||
|
inner_stream.extend(replace_variables(block.contents.clone()).1);
|
||||||
|
},
|
||||||
|
ComponentType::RealComponent => {
|
||||||
|
inner_stream.extend(TokenStream::from(quote!(self.)));
|
||||||
|
inner_stream.extend(Some(TokenTree::Ident(Ident::new(&format!("comp{}", component_index), Span::call_site()))));
|
||||||
|
inner_stream.extend(TokenStream::from(quote!(.lock().unwrap().set)));
|
||||||
|
|
||||||
|
let mut component_set_stream = TokenStream::new();
|
||||||
|
|
||||||
|
component_set_stream.extend(Some(TokenTree::Ident(block.prop_ident.clone().unwrap())));
|
||||||
|
component_set_stream.extend(TokenStream::from(quote!(: Option::Some)));
|
||||||
|
|
||||||
|
let component_set_some_stream = replace_variables(block.contents.clone()).1;
|
||||||
|
|
||||||
|
let mut component_set_group = Group::new(proc_macro::Delimiter::Parenthesis, component_set_some_stream);
|
||||||
|
component_set_stream.extend(Some(TokenTree::Group(component_set_group)));
|
||||||
|
|
||||||
|
component_set_stream.extend(TokenStream::from(quote!(, ..Default::default())));
|
||||||
|
|
||||||
|
let component_set_group = Group::new(proc_macro::Delimiter::Brace, component_set_stream);
|
||||||
|
let mut component_set_outer_stream = TokenStream::new();
|
||||||
|
|
||||||
|
let name = component.name.clone().to_string();
|
||||||
|
|
||||||
|
component_set_outer_stream.extend(Some(TokenTree::Ident(Ident::new(&format!("Partial{}Attributes", name), Span::call_site()))));
|
||||||
|
|
||||||
|
component_set_outer_stream.extend(Some(TokenTree::Group(component_set_group)));
|
||||||
|
let component_set_outer_group = Group::new(proc_macro::Delimiter::Parenthesis, component_set_outer_stream);
|
||||||
|
|
||||||
|
inner_stream.extend(Some(TokenTree::Group(component_set_outer_group)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let inner_group = Group::new(proc_macro::Delimiter::Brace, inner_stream);
|
||||||
|
update_stream.extend(Some(TokenTree::Group(inner_group)));
|
||||||
|
}
|
||||||
|
component_index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
let update_group = Group::new(proc_macro::Delimiter::Brace, update_stream);
|
let update_group = Group::new(proc_macro::Delimiter::Brace, update_stream);
|
||||||
component_impl_stream.extend(Some(TokenTree::Group(update_group)));
|
component_impl_stream.extend(Some(TokenTree::Group(update_group)));
|
||||||
|
|
||||||
|
|
@ -1051,12 +1134,54 @@ fn parse_components(name: Ident, group: Group, next: usize, parent: Option<usize
|
||||||
_ => panic!("Expected group after |param|")
|
_ => panic!("Expected group after |param|")
|
||||||
};
|
};
|
||||||
|
|
||||||
let this_component = components_found.get_mut(next).unwrap();
|
let this_component = components_found.get_mut(0).unwrap();
|
||||||
this_component.event_listeners.push(EventListener {
|
this_component.event_listeners.push(EventListener {
|
||||||
callback: fn_group,
|
callback: fn_group,
|
||||||
identifier: fn_param
|
identifier: fn_param
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
TokenTree::Ident(ident) => {
|
||||||
|
let ident_str = ident.to_string();
|
||||||
|
self_stream.extend(Some(TokenTree::Ident(ident.clone())));
|
||||||
|
let nexttoken = group.next();
|
||||||
|
match nexttoken {
|
||||||
|
None => {},
|
||||||
|
Some(token) => match token {
|
||||||
|
TokenTree::Punct(punct) if punct.as_char() == ':' => {
|
||||||
|
self_stream.extend(Some(TokenTree::Punct(punct)));
|
||||||
|
// likely reactive property
|
||||||
|
let mut property_stream = TokenStream::new();
|
||||||
|
while let Some(token) = group.next() {
|
||||||
|
match token {
|
||||||
|
TokenTree::Punct(punct) => {
|
||||||
|
let char = punct.as_char();
|
||||||
|
property_stream.extend(Some(TokenTree::Punct(punct)));
|
||||||
|
if char == ',' {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
property_stream.extend(Some(token));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let (reactive_variables, property_stream) = replace_variables(property_stream);
|
||||||
|
if reactive_variables.len() > 0 {
|
||||||
|
let this_component = components_found.get_mut(0).unwrap();
|
||||||
|
this_component.reactive_props.insert(ident_str, ReactiveBlock {
|
||||||
|
variables: reactive_variables,
|
||||||
|
contents: property_stream.clone(),
|
||||||
|
prop_ident: Some(ident)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self_stream.extend(property_stream);
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
self_stream.extend(Some(token));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
any => {
|
any => {
|
||||||
// skip until next ',', writing to self_stream
|
// skip until next ',', writing to self_stream
|
||||||
self_stream.extend(Some(any));
|
self_stream.extend(Some(any));
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ impl Component for Rectangle {
|
||||||
let mut to_update = [0; Self::UPDATE_LENGTH];
|
let mut to_update = [0; Self::UPDATE_LENGTH];
|
||||||
if let Some(radius) = attrs.radius {
|
if let Some(radius) = attrs.radius {
|
||||||
self.attrs.radius = radius;
|
self.attrs.radius = radius;
|
||||||
dbg!("Radius set", radius);
|
|
||||||
to_update[0] |= 1;
|
to_update[0] |= 1;
|
||||||
}
|
}
|
||||||
if to_update.into_iter().reduce(|a,b| a+b).unwrap() != 0 {
|
if to_update.into_iter().reduce(|a,b| a+b).unwrap() != 0 {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue