mirror of
https://github.com/danbulant/mangui
synced 2026-06-09 17:41:08 +00:00
working codegen for events and variable replacement
This commit is contained in:
parent
527af977e5
commit
6979feb37f
2 changed files with 129 additions and 26 deletions
|
|
@ -27,7 +27,7 @@ impl Component for DemoComponent {
|
||||||
type PartialComponentAttrs = PartialDemoComponentAttributes;
|
type PartialComponentAttrs = PartialDemoComponentAttributes;
|
||||||
fn new(attrs: Self::ComponentAttrs, selfref: WeakSharedComponent<Self>) -> Self {
|
fn new(attrs: Self::ComponentAttrs, selfref: WeakSharedComponent<Self>) -> Self {
|
||||||
let test = Arc::new(Mutex::new(Invalidator::new(false)));
|
let test = Arc::new(Mutex::new(Invalidator::new(false)));
|
||||||
let self_ = Self {
|
let this = Self {
|
||||||
rect: Arc::new_cyclic(|selfref| Mutex::new(Rectangle::new(RectangleAttributes { ..Default::default() }, selfref.clone()))),
|
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 {
|
||||||
|
|
@ -46,12 +46,12 @@ impl Component for DemoComponent {
|
||||||
selfref,
|
selfref,
|
||||||
test
|
test
|
||||||
};
|
};
|
||||||
let selfref = self_.selfref.clone();
|
let selfref = this.selfref.clone();
|
||||||
self_.layout.write().unwrap().events.add_handler(Box::new(move |event| {
|
this.layout.write().unwrap().events.add_handler(Box::new(move |event| {
|
||||||
let selfref = selfref.upgrade().unwrap();
|
let selfref = selfref.upgrade().unwrap();
|
||||||
let self_ = selfref.lock().unwrap();
|
let this = selfref.lock().unwrap();
|
||||||
let test = &self_.test;
|
let attrs = &this.attrs;
|
||||||
let attrs = &self_.attrs;
|
let test = &this.test;
|
||||||
match event.event {
|
match event.event {
|
||||||
mangui::events::InnerEvent::MouseDown(_) => {
|
mangui::events::InnerEvent::MouseDown(_) => {
|
||||||
**test.lock().unwrap() = true;
|
**test.lock().unwrap() = true;
|
||||||
|
|
@ -62,7 +62,7 @@ impl Component for DemoComponent {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
self_
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set(&mut self, _attrs: Self::PartialComponentAttrs) { }
|
fn set(&mut self, _attrs: Self::PartialComponentAttrs) { }
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,17 @@ use quote::quote;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Attribute {
|
struct Attribute {
|
||||||
name: Ident,
|
name: Ident,
|
||||||
|
/// Default value - ignored in Attributes, required in variables
|
||||||
default: Option<TokenStream>,
|
default: Option<TokenStream>,
|
||||||
type_: TokenStream
|
type_: TokenStream
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct EventListener {
|
struct EventListener {
|
||||||
callback: TokenStream
|
/// The callback itself, as the group
|
||||||
|
callback: Group,
|
||||||
|
/// The identifier of 'event' argument in callback (usually just event)
|
||||||
|
identifier: Ident
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -228,8 +232,6 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg!(&components_used);
|
|
||||||
|
|
||||||
let mut output = TokenStream::new();
|
let mut output = TokenStream::new();
|
||||||
|
|
||||||
// Component struct
|
// Component struct
|
||||||
|
|
@ -268,7 +270,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
for variable in &reactive_variables {
|
for variable in &reactive_variables {
|
||||||
component_struct_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
component_struct_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||||
component_struct_stream.extend(TokenStream::from(quote!(:)));
|
component_struct_stream.extend(TokenStream::from(quote!(:)));
|
||||||
component_struct_stream.extend(TokenStream::from(quote!(Arc<Mutex<Invalidator<)));
|
component_struct_stream.extend(TokenStream::from(quote!(std::sync::Arc<std::sync::Mutex<rusalka::invalidator::Invalidator<)));
|
||||||
component_struct_stream.extend(variable.type_.clone());
|
component_struct_stream.extend(variable.type_.clone());
|
||||||
component_struct_stream.extend(TokenStream::from(quote!(>>>)));
|
component_struct_stream.extend(TokenStream::from(quote!(>>>)));
|
||||||
component_struct_stream.extend(TokenStream::from(quote!(,)));
|
component_struct_stream.extend(TokenStream::from(quote!(,)));
|
||||||
|
|
@ -388,12 +390,15 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
new_stream.extend(TokenStream::from(quote!(let)));
|
new_stream.extend(TokenStream::from(quote!(let)));
|
||||||
new_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
new_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||||
new_stream.extend(TokenStream::from(quote!(:)));
|
new_stream.extend(TokenStream::from(quote!(:)));
|
||||||
// new_stream.extend(TokenStream::from(quote!(Arc::new(Mutex::new(Invalidator::new)))));
|
new_stream.extend(TokenStream::from(quote!(std::sync::Arc<std::sync::Mutex<rusalka::invalidator::Invalidator<)));
|
||||||
|
new_stream.extend(variable.type_.clone());
|
||||||
|
new_stream.extend(TokenStream::from(quote!(>>>)));
|
||||||
|
new_stream.extend(TokenStream::from(quote!(=)));
|
||||||
|
|
||||||
let mut invalidator = TokenStream::from(quote!(rusalka::invalidator::Invalidator::new));
|
let mut invalidator = TokenStream::from(quote!(rusalka::invalidator::Invalidator::new));
|
||||||
let mut invalidator_inner = TokenStream::new();
|
let mut invalidator_inner = TokenStream::new();
|
||||||
if let Some(def) = &variable.default {
|
if let Some(def) = &variable.default {
|
||||||
invalidator_inner.extend(def.clone());
|
invalidator_inner.extend(replace_variables(def.clone()));
|
||||||
} else {
|
} else {
|
||||||
invalidator_inner.extend(TokenStream::from(quote!(Default::default())));
|
invalidator_inner.extend(TokenStream::from(quote!(Default::default())));
|
||||||
}
|
}
|
||||||
|
|
@ -405,7 +410,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
|
|
||||||
new_stream.extend(main_logic);
|
new_stream.extend(main_logic);
|
||||||
|
|
||||||
new_stream.extend(TokenStream::from(quote!(Self)));
|
new_stream.extend(TokenStream::from(quote!(let this = Self)));
|
||||||
|
|
||||||
let mut new_returnvalue_stream = TokenStream::new();
|
let mut new_returnvalue_stream = TokenStream::new();
|
||||||
|
|
||||||
|
|
@ -433,8 +438,8 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
// component_new_stream.extend(TokenStream::from(quote!(as Component>::ComponentAttrs)));
|
// component_new_stream.extend(TokenStream::from(quote!(as Component>::ComponentAttrs)));
|
||||||
|
|
||||||
component_new_stream.extend(Some(TokenTree::Ident(Ident::new(&format!("{}Attributes", component_name), Span::call_site()))));
|
component_new_stream.extend(Some(TokenTree::Ident(Ident::new(&format!("{}Attributes", component_name), Span::call_site()))));
|
||||||
|
|
||||||
let components_attributes_group = Group::new(proc_macro::Delimiter::Brace, component.contents.clone());
|
let components_attributes_group = Group::new(proc_macro::Delimiter::Brace, replace_variables(component.contents.clone()));
|
||||||
|
|
||||||
component_new_stream.extend(Some(TokenTree::Group(components_attributes_group)));
|
component_new_stream.extend(Some(TokenTree::Group(components_attributes_group)));
|
||||||
|
|
||||||
|
|
@ -447,7 +452,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
new_returnvalue_stream.extend(wrap_in_arcmutex_cyclic(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, replace_variables(component.contents.clone()));
|
||||||
component_stream.extend(Some(TokenTree::Group(node_group)));
|
component_stream.extend(Some(TokenTree::Group(node_group)));
|
||||||
new_returnvalue_stream.extend(wrap_in_arcrwlock(component_stream));
|
new_returnvalue_stream.extend(wrap_in_arcrwlock(component_stream));
|
||||||
}
|
}
|
||||||
|
|
@ -457,11 +462,79 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
i+=1;
|
i+=1;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_returnvalue_stream.extend(TokenStream::from(quote!(attrs, selfref)));
|
new_returnvalue_stream.extend(TokenStream::from(quote!(attrs, selfref,)));
|
||||||
|
|
||||||
|
for variable in &reactive_variables {
|
||||||
|
new_returnvalue_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||||
|
new_returnvalue_stream.extend(TokenStream::from(quote!(,)));
|
||||||
|
}
|
||||||
|
|
||||||
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)));
|
||||||
|
|
||||||
|
new_stream.extend(TokenStream::from(quote!(;)));
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for component in &components_used {
|
||||||
|
match component.component_type {
|
||||||
|
ComponentType::RealComponent => continue,
|
||||||
|
ComponentType::Node => {}
|
||||||
|
};
|
||||||
|
for event_listener in &component.event_listeners {
|
||||||
|
new_stream.extend(TokenStream::from(quote!(let selfref = this.selfref.clone();)));
|
||||||
|
new_stream.extend(TokenStream::from(quote!(this.)));
|
||||||
|
new_stream.extend(Some(TokenTree::Ident(Ident::new(&format!("comp{}", i), Span::call_site()))));
|
||||||
|
|
||||||
|
// Change the following line according to how realcomponents want it - this is for nodes only
|
||||||
|
new_stream.extend(TokenStream::from(quote!(.write().unwrap().events.add_handler)));
|
||||||
|
|
||||||
|
let mut box_stream = TokenStream::new();
|
||||||
|
|
||||||
|
box_stream.extend(TokenStream::from(quote!(Box::new)));
|
||||||
|
|
||||||
|
let mut callback_stream = TokenStream::new();
|
||||||
|
|
||||||
|
callback_stream.extend(TokenStream::from(quote!(move |)));
|
||||||
|
callback_stream.extend(Some(TokenTree::Ident(event_listener.identifier.clone())));
|
||||||
|
callback_stream.extend(TokenStream::from(quote!(|)));
|
||||||
|
|
||||||
|
let mut inner_callback_stream = TokenStream::new();
|
||||||
|
|
||||||
|
inner_callback_stream.extend(TokenStream::from(quote!(
|
||||||
|
let selfref = selfref.upgrade().unwrap();
|
||||||
|
let this = selfref.lock().unwrap();
|
||||||
|
let attrs = &this.attrs;
|
||||||
|
)));
|
||||||
|
|
||||||
|
for variable in &reactive_variables {
|
||||||
|
inner_callback_stream.extend(TokenStream::from(quote!(let)));
|
||||||
|
inner_callback_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||||
|
inner_callback_stream.extend(TokenStream::from(quote!(= &this.)));
|
||||||
|
inner_callback_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||||
|
inner_callback_stream.extend(TokenStream::from(quote!(;)));
|
||||||
|
}
|
||||||
|
|
||||||
|
inner_callback_stream.extend(replace_variables(event_listener.callback.clone().stream()));
|
||||||
|
|
||||||
|
let callback_group = Group::new(proc_macro::Delimiter::Brace, inner_callback_stream);
|
||||||
|
|
||||||
|
callback_stream.extend(Some(TokenTree::Group(callback_group)));
|
||||||
|
|
||||||
|
let callback_group = Group::new(proc_macro::Delimiter::Parenthesis, callback_stream);
|
||||||
|
|
||||||
|
box_stream.extend(Some(TokenTree::Group(callback_group)));
|
||||||
|
|
||||||
|
let box_group = Group::new(proc_macro::Delimiter::Parenthesis, box_stream);
|
||||||
|
|
||||||
|
new_stream.extend(Some(TokenTree::Group(box_group)));
|
||||||
|
|
||||||
|
new_stream.extend(TokenStream::from(quote!(;)));
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_stream.extend(TokenStream::from(quote!(this)));
|
||||||
|
|
||||||
let new_group = Group::new(proc_macro::Delimiter::Brace, new_stream);
|
let new_group = Group::new(proc_macro::Delimiter::Brace, new_stream);
|
||||||
component_impl_stream.extend(Some(TokenTree::Group(new_group)));
|
component_impl_stream.extend(Some(TokenTree::Group(new_group)));
|
||||||
|
|
||||||
|
|
@ -662,6 +735,41 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replaces $variable with **variable.lock().unwrap()
|
||||||
|
fn replace_variables(stream: TokenStream) -> TokenStream {
|
||||||
|
let mut output = TokenStream::new();
|
||||||
|
|
||||||
|
let mut stream = stream.into_iter();
|
||||||
|
|
||||||
|
while let Some(token) = stream.next() {
|
||||||
|
match token {
|
||||||
|
TokenTree::Punct(punct) if punct.as_char() == '$' => {
|
||||||
|
let ident = stream.next().unwrap();
|
||||||
|
let ident = match ident {
|
||||||
|
TokenTree::Ident(ident) => ident,
|
||||||
|
_ => panic!("Expected ident after $")
|
||||||
|
};
|
||||||
|
output.extend(TokenStream::from(quote!(**)));
|
||||||
|
output.extend(Some(TokenTree::Ident(ident.clone())));
|
||||||
|
output.extend(TokenStream::from(quote!(.lock().unwrap())));
|
||||||
|
},
|
||||||
|
TokenTree::Group(group) => {
|
||||||
|
let group_delim = group.delimiter();
|
||||||
|
let span = group.span();
|
||||||
|
let groupstream = replace_variables(group.stream());
|
||||||
|
let mut group = Group::new(group_delim, groupstream);
|
||||||
|
group.set_span(span);
|
||||||
|
output.extend(Some(TokenTree::Group(group)));
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
output.extend(Some(token));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
fn wrap_in_arc_mutex(stream: TokenStream) -> TokenStream {
|
fn wrap_in_arc_mutex(stream: TokenStream) -> TokenStream {
|
||||||
let mut output = TokenStream::new();
|
let mut output = TokenStream::new();
|
||||||
|
|
||||||
|
|
@ -778,7 +886,7 @@ fn parse_components(name: Ident, group: Group, next: usize, parent: Option<usize
|
||||||
let fn_start = group.next().unwrap();
|
let fn_start = group.next().unwrap();
|
||||||
match fn_start {
|
match fn_start {
|
||||||
TokenTree::Punct(punct) if punct.as_char() == '|' => {},
|
TokenTree::Punct(punct) if punct.as_char() == '|' => {},
|
||||||
_ => panic!("Expected | after $ (event handlers). Move is added automatically")
|
_ => panic!("Expected | after $ (event handlers). Move is added automatically. If you want to use a reactive variable, use variable: $variable instead")
|
||||||
}
|
}
|
||||||
let fn_param = group.next().unwrap();
|
let fn_param = group.next().unwrap();
|
||||||
let fn_param = match fn_param {
|
let fn_param = match fn_param {
|
||||||
|
|
@ -797,15 +905,10 @@ fn parse_components(name: Ident, group: Group, next: usize, parent: Option<usize
|
||||||
_ => panic!("Expected group after |param|")
|
_ => 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();
|
let this_component = components_found.get_mut(next).unwrap();
|
||||||
this_component.event_listeners.push(EventListener {
|
this_component.event_listeners.push(EventListener {
|
||||||
callback: callback_stream
|
callback: fn_group,
|
||||||
|
identifier: fn_param
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
any => {
|
any => {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue