mirror of
https://github.com/danbulant/mangui
synced 2026-05-19 03:58:34 +00:00
rusalka: progress on reactivity, native nodes support
This commit is contained in:
parent
38473da15f
commit
3d6ac6cdcf
7 changed files with 418 additions and 94 deletions
|
|
@ -1,32 +1,59 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
use mangui::SharedNode;
|
||||
use rusalka::{component::Component, nodes::primitives::{Rectangle, RectangleAttributes}, SharedComponent};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use mangui::{SharedNode, nodes::{layout::Layout, Style}, taffy::prelude::Size};
|
||||
use rusalka::{component::Component, nodes::{primitives::{Rectangle, RectangleAttributes}, insert, detach}, SharedComponent};
|
||||
|
||||
pub struct DemoComponent {
|
||||
rect: SharedComponent<Rectangle>,
|
||||
attrs: DemoComponentAttributes,
|
||||
layout: Arc<RwLock<Layout>>
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DemoComponentAttributes {}
|
||||
#[derive(Default)]
|
||||
pub struct PartialDemoComponentAttributes {}
|
||||
|
||||
impl From<DemoComponentAttributes> for PartialDemoComponentAttributes {
|
||||
fn from(_attrs: DemoComponentAttributes) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Component for DemoComponent {
|
||||
type ComponentAttrs = DemoComponentAttributes;
|
||||
type PartialComponentAttrs = PartialDemoComponentAttributes;
|
||||
fn new(attrs: Self::ComponentAttrs) -> Self {
|
||||
Self {
|
||||
rect: Arc::new(Mutex::new(Rectangle::new(RectangleAttributes {}))),
|
||||
rect: Arc::new(Mutex::new(Rectangle::new(RectangleAttributes { ..Default::default() }))),
|
||||
layout: Arc::new(RwLock::new(Layout {
|
||||
style: Style {
|
||||
layout: mangui::nodes::TaffyStyle {
|
||||
min_size: Size {
|
||||
width: mangui::taffy::style::Dimension::Points(50.),
|
||||
height: mangui::taffy::style::Dimension::Points(100.)
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})),
|
||||
attrs,
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, attrs: Self::ComponentAttrs) { self.attrs = attrs; }
|
||||
fn set(&mut self, _attrs: Self::PartialComponentAttrs) { }
|
||||
fn get(&self) -> &Self::ComponentAttrs { &self.attrs }
|
||||
fn mount(&self, parent: &SharedNode, before: Option<&SharedNode>) {
|
||||
self.rect.lock().unwrap().mount(parent, before);
|
||||
insert(parent, &{self.layout.clone()}, before);
|
||||
self.rect.lock().unwrap().mount(&{self.layout.clone()}, None);
|
||||
}
|
||||
|
||||
fn unmount(&self) {
|
||||
self.rect.lock().unwrap().unmount();
|
||||
detach(&{self.layout.clone()});
|
||||
}
|
||||
|
||||
fn update(&self) {}
|
||||
fn update(&self, _bitmap: &[u32]) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,21 @@
|
|||
use rusalka_macro::make_component;
|
||||
use std::default::Default;
|
||||
use mangui::{SharedNode, nodes::Style, taffy::prelude::Size, femtovg::{Paint, Color}};
|
||||
use mangui::{SharedNode, nodes::Style, taffy::prelude::Size, femtovg::{Paint, Color}, nodes::layout::Layout};
|
||||
|
||||
use rusalka::nodes::primitives::{Rectangle, RectangleAttributes};
|
||||
|
||||
make_component!(
|
||||
ComponentDemo,
|
||||
Logic {
|
||||
let test = false;
|
||||
let radius = 5.;
|
||||
}
|
||||
Component {
|
||||
@Rectangle {
|
||||
// style: Style {
|
||||
// layout: TaffyStyle {
|
||||
// min_size: Size {
|
||||
// width: Dimension::Points(50.),
|
||||
// height: Dimension::Points(100.)
|
||||
// },
|
||||
// ..Default::default()
|
||||
// },
|
||||
// ..Default::default()
|
||||
// },
|
||||
// fill: Paint::color(Color::rgb(0, 0, 255)),
|
||||
// radius: 5.,
|
||||
// ..Default::default()
|
||||
@layout {
|
||||
@Rectangle {
|
||||
radius,
|
||||
..Default::default()
|
||||
}
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,20 +1,29 @@
|
|||
use proc_macro::{TokenStream, TokenTree, Ident, Group, Punct, Span};
|
||||
use quote::quote;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Attribute {
|
||||
name: Ident,
|
||||
default: Option<TokenStream>,
|
||||
type_: TokenStream
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ComponentType {
|
||||
RealComponent,
|
||||
Node
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ComponentUsed {
|
||||
name: Ident,
|
||||
contents: TokenStream,
|
||||
parent: Option<usize>
|
||||
parent: Option<usize>,
|
||||
component_type: ComponentType
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
/// If you have syntax errors because of attributes, wrap the default value in parentheses.
|
||||
pub fn make_component(item: TokenStream) -> TokenStream {
|
||||
dbg!(&item);
|
||||
|
||||
|
|
@ -26,7 +35,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
dbg!(&name);
|
||||
|
||||
// let mut attributes: Vec<Attribute> = Vec::new();
|
||||
let mut attributes: Vec<Attribute> = Vec::new();
|
||||
|
||||
// let mut struct_values = Vec::new();
|
||||
|
||||
|
|
@ -42,18 +51,110 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
last_identifier = Some(ident.to_string());
|
||||
let ident = ident.to_string();
|
||||
|
||||
if ident == "Logic" {
|
||||
// dbg!("Logic");
|
||||
} else if ident == "Component" {
|
||||
// dbg!("Component");
|
||||
} else {
|
||||
panic!("Unknown identifier: {:?}", ident);
|
||||
match ident.as_str() {
|
||||
"Logic" | "Component" | "Attributes" => {},
|
||||
_ => panic!("Unknown identifier: {:?}", ident)
|
||||
}
|
||||
},
|
||||
TokenTree::Group(group) => {
|
||||
match &last_identifier {
|
||||
Some(ident) => {
|
||||
match ident.as_str() {
|
||||
"Attributes" => {
|
||||
// A struct-like definition of attributes
|
||||
// Example syntax:
|
||||
// Attributes { // we're here
|
||||
// radius: f32 = 5.,
|
||||
// fill: Paint,
|
||||
// something: Something<(dyn Test)>
|
||||
// }
|
||||
// we need to match <> together, other groupings are already done by rust
|
||||
|
||||
let mut stream = group.stream().into_iter();
|
||||
|
||||
while let Some(token) = stream.next() {
|
||||
let name = match token {
|
||||
TokenTree::Ident(ident) => ident,
|
||||
_ => panic!("Expected ident")
|
||||
};
|
||||
|
||||
let colon = stream.next().unwrap();
|
||||
let colon = match colon {
|
||||
TokenTree::Punct(punct) => {
|
||||
if punct.as_char() != ':' {
|
||||
panic!("Expected :");
|
||||
}
|
||||
punct
|
||||
},
|
||||
_ => panic!("Expected :")
|
||||
};
|
||||
|
||||
let mut type_ = TokenStream::new();
|
||||
|
||||
let mut last_was_set = false;
|
||||
let mut ltgt_count = 0;
|
||||
|
||||
while let Some(token) = stream.next() {
|
||||
match token {
|
||||
TokenTree::Ident(ident) => {
|
||||
type_.extend(Some(TokenTree::Ident(ident)));
|
||||
},
|
||||
TokenTree::Punct(punct) => {
|
||||
if ltgt_count == 0 && punct.as_char() == ',' {
|
||||
break;
|
||||
} else if ltgt_count == 0 && punct.as_char() == '=' {
|
||||
last_was_set = true;
|
||||
break;
|
||||
} else {
|
||||
if punct.as_char() == '<' {
|
||||
ltgt_count += 1;
|
||||
} else if punct.as_char() == '>' {
|
||||
ltgt_count -= 1;
|
||||
}
|
||||
type_.extend(Some(TokenTree::Punct(punct)));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
type_.extend(Some(token));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if last_was_set {
|
||||
let mut default = TokenStream::new();
|
||||
|
||||
while let Some(token) = stream.next() {
|
||||
match token {
|
||||
TokenTree::Ident(ident) => {
|
||||
default.extend(Some(TokenTree::Ident(ident)));
|
||||
},
|
||||
TokenTree::Punct(punct) => {
|
||||
if punct.as_char() == ',' {
|
||||
break;
|
||||
} else {
|
||||
default.extend(Some(TokenTree::Punct(punct)));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
default.extend(Some(token));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attributes.push(Attribute {
|
||||
name,
|
||||
default: Some(default),
|
||||
type_
|
||||
});
|
||||
} else {
|
||||
attributes.push(Attribute {
|
||||
name,
|
||||
default: None,
|
||||
type_
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
"Logic" => {
|
||||
main_logic.push(group.stream());
|
||||
},
|
||||
|
|
@ -131,7 +232,16 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
let ident = Ident::new(&format!("comp{}", i), Span::call_site());
|
||||
|
||||
let midstream = TokenStream::from(quote!(: rusalka::SharedComponent<));
|
||||
let mut midstream = TokenStream::from(quote!(: rusalka::));
|
||||
|
||||
match component.component_type {
|
||||
ComponentType::RealComponent => {
|
||||
midstream.extend(TokenStream::from(quote!(SharedComponent<)));
|
||||
},
|
||||
ComponentType::Node => {
|
||||
midstream.extend(TokenStream::from(quote!(SharedNodeComponent<)));
|
||||
}
|
||||
}
|
||||
|
||||
let component_name = component.name.clone();
|
||||
|
||||
|
|
@ -153,14 +263,44 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
let component_struct_group = Group::new(proc_macro::Delimiter::Brace, component_struct_stream);
|
||||
output.extend(Some(TokenTree::Group(component_struct_group)));
|
||||
|
||||
let attributes_struct_stream = TokenStream::new();
|
||||
|
||||
// attributes TBD
|
||||
|
||||
output.extend(TokenStream::from(quote!(pub struct)));
|
||||
let attributes_struct_stream = TokenStream::new();
|
||||
output.extend(TokenStream::from(quote!(#[derive(Default)] pub struct)));
|
||||
output.extend(Some(TokenTree::Ident(attributes_ident.clone())));
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, attributes_struct_stream))));
|
||||
|
||||
// partial attributes
|
||||
|
||||
let partial_attributes_ident = Ident::new(&format!("Partial{str_name}Attributes"), Span::call_site());
|
||||
output.extend(TokenStream::from(quote!(#[derive(Default)] pub struct)));
|
||||
output.extend(Some(TokenTree::Ident(partial_attributes_ident.clone())));
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, TokenStream::new()))));
|
||||
|
||||
// impl From<Attributes> for PartialAttributes
|
||||
|
||||
output.extend(TokenStream::from(quote!(impl From<)));
|
||||
output.extend(Some(TokenTree::Ident(attributes_ident.clone())));
|
||||
output.extend(TokenStream::from(quote!(> for)));
|
||||
output.extend(Some(TokenTree::Ident(partial_attributes_ident.clone())));
|
||||
|
||||
let mut from_stream = TokenStream::new();
|
||||
|
||||
from_stream.extend(TokenStream::from(quote!(fn from)));
|
||||
|
||||
let mut from_args = TokenStream::new();
|
||||
from_args.extend(TokenStream::from(quote!(attrs:)));
|
||||
from_args.extend(Some(TokenTree::Ident(attributes_ident.clone())));
|
||||
from_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Parenthesis, from_args))));
|
||||
from_stream.extend(TokenStream::from(quote!(-> Self)));
|
||||
|
||||
let mut from_fn_stream = TokenStream::new();
|
||||
from_fn_stream.extend(TokenStream::from(quote!(Self {})));
|
||||
|
||||
from_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, from_fn_stream))));
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, from_stream))));
|
||||
|
||||
// Component impl
|
||||
|
||||
output.extend(TokenStream::from(quote!(impl rusalka::component::Component for)));
|
||||
|
|
@ -171,6 +311,9 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
component_impl_stream.extend(TokenStream::from(quote!(type ComponentAttrs =)));
|
||||
component_impl_stream.extend(Some(TokenTree::Ident(attributes_ident.clone())));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(;)));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(type PartialComponentAttrs =)));
|
||||
component_impl_stream.extend(Some(TokenTree::Ident(partial_attributes_ident.clone())));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(;)));
|
||||
|
||||
// fn new
|
||||
|
||||
|
|
@ -196,25 +339,36 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
let mut component_stream = TokenStream::new();
|
||||
|
||||
component_stream.extend(Some(TokenTree::Ident(component_name.clone())));
|
||||
component_stream.extend(TokenStream::from(quote!(::new)));
|
||||
|
||||
let mut component_new_stream = TokenStream::new();
|
||||
match component.component_type {
|
||||
ComponentType::RealComponent => {
|
||||
component_stream.extend(TokenStream::from(quote!(::new)));
|
||||
|
||||
let component_attributes = Ident::new(&format!("{}Attributes", component_name.to_string()), Span::call_site());
|
||||
|
||||
component_new_stream.extend(Some(TokenTree::Ident(component_attributes)));
|
||||
|
||||
let component_attributes_group_stream = TokenStream::new();
|
||||
|
||||
let components_attributes_group = Group::new(proc_macro::Delimiter::Brace, component_attributes_group_stream);
|
||||
|
||||
component_new_stream.extend(Some(TokenTree::Group(components_attributes_group)));
|
||||
|
||||
let component_new_group = Group::new(proc_macro::Delimiter::Parenthesis, component_new_stream);
|
||||
|
||||
component_stream.extend(Some(TokenTree::Group(component_new_group)));
|
||||
|
||||
new_returnvalue_stream.extend(wrap_in_arcmutex(component_stream));
|
||||
let mut component_new_stream = TokenStream::new();
|
||||
|
||||
// The following would allow not importing ComponentAttributes, but rust doesn't support it outside of nightly just yet
|
||||
// component_new_stream.extend(Some(TokenTree::Punct(Punct::new('<', proc_macro::Spacing::Alone))));
|
||||
// component_new_stream.extend(Some(TokenTree::Ident(component_name.clone())));
|
||||
// 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()))));
|
||||
|
||||
let components_attributes_group = Group::new(proc_macro::Delimiter::Brace, component.contents.clone());
|
||||
|
||||
component_new_stream.extend(Some(TokenTree::Group(components_attributes_group)));
|
||||
|
||||
let component_new_group = Group::new(proc_macro::Delimiter::Parenthesis, component_new_stream);
|
||||
|
||||
component_stream.extend(Some(TokenTree::Group(component_new_group)));
|
||||
|
||||
new_returnvalue_stream.extend(wrap_in_arcmutex(component_stream));
|
||||
},
|
||||
ComponentType::Node => {
|
||||
let node_group = Group::new(proc_macro::Delimiter::Brace, component.contents.clone());
|
||||
component_stream.extend(Some(TokenTree::Group(node_group)));
|
||||
new_returnvalue_stream.extend(wrap_in_arcrwlock(component_stream));
|
||||
}
|
||||
}
|
||||
new_returnvalue_stream.extend(TokenStream::from(quote!(,)));
|
||||
|
||||
i+=1;
|
||||
|
|
@ -230,7 +384,10 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
// fn set
|
||||
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn set(&mut self, attrs: Self::ComponentAttrs) { self.attrs = attrs; })));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn set(&mut self, attrs: Self::PartialComponentAttrs))));
|
||||
let set_stream = TokenStream::new();
|
||||
|
||||
component_impl_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, set_stream))));
|
||||
|
||||
// fn get
|
||||
|
||||
|
|
@ -244,25 +401,75 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
for i in 0..components_used.len() {
|
||||
let ident = Ident::new(&format!("comp{}", i), Span::call_site());
|
||||
let component = &components_used.get(i).unwrap();
|
||||
|
||||
let mut component_stream = TokenStream::new();
|
||||
match component.component_type {
|
||||
ComponentType::RealComponent => {
|
||||
let mut component_stream = TokenStream::new();
|
||||
|
||||
component_stream.extend(TokenStream::from(quote!(self.)));
|
||||
component_stream.extend(Some(TokenTree::Ident(ident)));
|
||||
component_stream.extend(TokenStream::from(quote!(.lock().unwrap().mount)));
|
||||
|
||||
let mut component_mount_stream = TokenStream::new();
|
||||
|
||||
component_stream.extend(TokenStream::from(quote!(self.)));
|
||||
component_stream.extend(Some(TokenTree::Ident(ident)));
|
||||
component_stream.extend(TokenStream::from(quote!(.lock().unwrap().mount)));
|
||||
match component.parent {
|
||||
Some(parent) => {
|
||||
let parent_ident = Ident::new(&format!("comp{}", parent), Span::call_site());
|
||||
|
||||
let mut component_mount_stream = TokenStream::new();
|
||||
let mut node_insert_self_stream = TokenStream::new();
|
||||
|
||||
component_mount_stream.extend(TokenStream::from(quote!(parent)));
|
||||
component_mount_stream.extend(TokenStream::from(quote!(,)));
|
||||
component_mount_stream.extend(TokenStream::from(quote!(before)));
|
||||
node_insert_self_stream.extend(TokenStream::from(quote!(self.)));
|
||||
node_insert_self_stream.extend(Some(TokenTree::Ident(parent_ident)));
|
||||
node_insert_self_stream.extend(TokenStream::from(quote!(.clone())));
|
||||
|
||||
let component_mount_group = Group::new(proc_macro::Delimiter::Parenthesis, component_mount_stream);
|
||||
let node_insert_self_group = Group::new(proc_macro::Delimiter::Brace, node_insert_self_stream);
|
||||
component_mount_stream.extend(TokenStream::from(quote!(&)));
|
||||
component_mount_stream.extend(Some(TokenTree::Group(node_insert_self_group)));
|
||||
},
|
||||
None => {
|
||||
component_mount_stream.extend(TokenStream::from(quote!(parent)));
|
||||
}
|
||||
}
|
||||
component_mount_stream.extend(TokenStream::from(quote!(,)));
|
||||
component_mount_stream.extend(TokenStream::from(quote!(before)));
|
||||
|
||||
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(component_stream);
|
||||
mount_stream.extend(TokenStream::from(quote!(;)));
|
||||
},
|
||||
ComponentType::Node => {
|
||||
let mut node_stream = TokenStream::new();
|
||||
|
||||
component_stream.extend(Some(TokenTree::Group(component_mount_group)));
|
||||
node_stream.extend(TokenStream::from(quote!(rusalka::nodes::insert)));
|
||||
|
||||
let mut node_insert_stream = TokenStream::new();
|
||||
|
||||
node_insert_stream.extend(TokenStream::from(quote!(parent,)));
|
||||
node_insert_stream.extend(TokenStream::from(quote!(&)));
|
||||
|
||||
let mut node_insert_self_stream = TokenStream::new();
|
||||
|
||||
node_insert_self_stream.extend(TokenStream::from(quote!(self.)));
|
||||
node_insert_self_stream.extend(Some(TokenTree::Ident(ident)));
|
||||
node_insert_self_stream.extend(TokenStream::from(quote!(.clone())));
|
||||
|
||||
let node_insert_self_group = Group::new(proc_macro::Delimiter::Brace, node_insert_self_stream);
|
||||
node_insert_stream.extend(Some(TokenTree::Group(node_insert_self_group)));
|
||||
|
||||
node_insert_stream.extend(TokenStream::from(quote!(,)));
|
||||
node_insert_stream.extend(TokenStream::from(quote!(before)));
|
||||
|
||||
node_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Parenthesis, node_insert_stream))));
|
||||
|
||||
mount_stream.extend(node_stream);
|
||||
mount_stream.extend(TokenStream::from(quote!(;)));
|
||||
}
|
||||
}
|
||||
|
||||
mount_stream.extend(component_stream);
|
||||
mount_stream.extend(TokenStream::from(quote!(;)));
|
||||
}
|
||||
|
||||
let mount_group = Group::new(proc_macro::Delimiter::Brace, mount_stream);
|
||||
|
|
@ -276,15 +483,39 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
for i in 0..components_used.len() {
|
||||
let ident = Ident::new(&format!("comp{}", i), Span::call_site());
|
||||
let component = &components_used.get(i).unwrap();
|
||||
|
||||
let mut component_stream = TokenStream::new();
|
||||
match component.component_type {
|
||||
ComponentType::RealComponent => {
|
||||
let mut component_stream = TokenStream::new();
|
||||
|
||||
component_stream.extend(TokenStream::from(quote!(self.)));
|
||||
component_stream.extend(Some(TokenTree::Ident(ident)));
|
||||
component_stream.extend(TokenStream::from(quote!(.lock().unwrap().unmount())));
|
||||
|
||||
unmount_stream.extend(component_stream);
|
||||
unmount_stream.extend(TokenStream::from(quote!(;)));
|
||||
},
|
||||
ComponentType::Node => {
|
||||
unmount_stream.extend(TokenStream::from(quote!(rusalka::nodes::detach)));
|
||||
|
||||
component_stream.extend(TokenStream::from(quote!(self.)));
|
||||
component_stream.extend(Some(TokenTree::Ident(ident)));
|
||||
component_stream.extend(TokenStream::from(quote!(.lock().unwrap().unmount())));
|
||||
let mut node_detach_stream = TokenStream::new();
|
||||
node_detach_stream.extend(TokenStream::from(quote!(&)));
|
||||
|
||||
unmount_stream.extend(component_stream);
|
||||
unmount_stream.extend(TokenStream::from(quote!(;)));
|
||||
let mut node_detach_self_stream = TokenStream::new();
|
||||
|
||||
node_detach_self_stream.extend(TokenStream::from(quote!(self.)));
|
||||
node_detach_self_stream.extend(Some(TokenTree::Ident(ident)));
|
||||
node_detach_self_stream.extend(TokenStream::from(quote!(.clone())));
|
||||
|
||||
let node_detach_self_group = Group::new(proc_macro::Delimiter::Brace, node_detach_self_stream);
|
||||
node_detach_stream.extend(Some(TokenTree::Group(node_detach_self_group)));
|
||||
|
||||
let node_detach_group = Group::new(proc_macro::Delimiter::Parenthesis, node_detach_stream);
|
||||
unmount_stream.extend(Some(TokenTree::Group(node_detach_group)));
|
||||
unmount_stream.extend(TokenStream::from(quote!(;)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let unmount_group = Group::new(proc_macro::Delimiter::Brace, unmount_stream);
|
||||
|
|
@ -292,11 +523,13 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
// fn update
|
||||
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn update(&self) {})));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn update(&self, bitmap: &[u32]) { self.check_update(bitmap); })));
|
||||
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, component_impl_stream))));
|
||||
|
||||
dbg!(&output);
|
||||
// dbg!(&output);
|
||||
|
||||
dbg!(attributes);
|
||||
|
||||
println!("{}", output.to_string());
|
||||
|
||||
|
|
@ -325,6 +558,26 @@ fn wrap_in_arcmutex(stream: TokenStream) -> TokenStream {
|
|||
output
|
||||
}
|
||||
|
||||
fn wrap_in_arcrwlock(stream: TokenStream) -> TokenStream {
|
||||
let mut output = TokenStream::new();
|
||||
|
||||
output.extend(TokenStream::from(quote!(std::sync::Arc::new)));
|
||||
|
||||
let mut mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream);
|
||||
|
||||
let mut mutex_stream = TokenStream::new();
|
||||
|
||||
mutex_stream.extend(TokenStream::from(quote!(std::sync::RwLock::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
|
||||
}
|
||||
|
||||
/// Call this after @
|
||||
/// Will return the main component as well as any sub-components
|
||||
/// name: the name of the component
|
||||
|
|
@ -339,10 +592,18 @@ fn parse_components(name: Ident, group: Group, next: usize, parent: Option<usize
|
|||
|
||||
// dbg!(&name);
|
||||
|
||||
let name_starts_lowercase = name.to_string().chars().next().unwrap().is_lowercase();
|
||||
|
||||
let this_component = ComponentUsed {
|
||||
name,
|
||||
name: if name_starts_lowercase {
|
||||
let mut str = name.to_string();
|
||||
str.replace_range(0..1, &str[0..1].to_uppercase());
|
||||
let span = name.span();
|
||||
Ident::new(&str, span)
|
||||
} else { name },
|
||||
contents: self_stream.clone(),
|
||||
parent
|
||||
parent,
|
||||
component_type: if name_starts_lowercase { ComponentType::Node } else { ComponentType::RealComponent }
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -367,6 +628,7 @@ fn parse_components(name: Ident, group: Group, next: usize, parent: Option<usize
|
|||
let components = parse_components(ident, group, next + components_found.len() + 1, Some(next));
|
||||
components_found.extend(components);
|
||||
} else {
|
||||
self_stream.extend(Some(TokenTree::Punct(punct)));
|
||||
while let Some(token) = group.next() {
|
||||
match token {
|
||||
TokenTree::Punct(punct) => {
|
||||
|
|
@ -383,16 +645,16 @@ fn parse_components(name: Ident, group: Group, next: usize, parent: Option<usize
|
|||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
any => {
|
||||
// skip until next ',', writing to self_stream
|
||||
|
||||
self_stream.extend(Some(any));
|
||||
while let Some(token) = group.next() {
|
||||
match token {
|
||||
TokenTree::Punct(punct) => {
|
||||
if punct.as_char() == ',' {
|
||||
let char = punct.as_char();
|
||||
self_stream.extend(Some(TokenTree::Punct(punct)));
|
||||
if char == ',' {
|
||||
break;
|
||||
} else {
|
||||
self_stream.extend(Some(TokenTree::Punct(punct)));
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
use mangui::SharedNode;
|
||||
use mangui::{SharedNode, nodes::Node};
|
||||
|
||||
/// A rusalka component
|
||||
pub trait Component {
|
||||
type ComponentAttrs;
|
||||
type ComponentAttrs: Default;
|
||||
type PartialComponentAttrs: Default + From<Self::ComponentAttrs>;
|
||||
const UPDATE_LENGTH : usize = 0;
|
||||
fn new(attr: Self::ComponentAttrs) -> Self;
|
||||
fn get(&self) -> &Self::ComponentAttrs;
|
||||
fn set(&mut self, attr: Self::ComponentAttrs);
|
||||
fn set(&mut self, attr: Self::PartialComponentAttrs);
|
||||
fn mount(&self, parent: &SharedNode, before: Option<&SharedNode>);
|
||||
fn update(&self);
|
||||
fn update(&self, bitmap: &[u32]);
|
||||
fn unmount(&self);
|
||||
}
|
||||
|
||||
fn check_update(&self, bitmap: &[u32]) -> () {
|
||||
if bitmap.len() != Self::UPDATE_LENGTH {
|
||||
panic!("Bitmap length does not match update length");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
|
||||
use component::Component;
|
||||
use mangui::nodes::Node;
|
||||
|
||||
pub mod component;
|
||||
pub mod nodes;
|
||||
|
||||
pub type SharedComponent<T: Component> = Arc<Mutex<T>>;
|
||||
pub type SharedComponent<T: Component> = Arc<Mutex<T>>;
|
||||
pub type SharedNodeComponent<T: Node> = Arc<RwLock<T>>;
|
||||
|
|
@ -3,7 +3,6 @@ use mangui::SharedNode;
|
|||
|
||||
pub mod primitives;
|
||||
|
||||
|
||||
pub fn detach(node: &SharedNode) {
|
||||
if let Some(parent) = node.read().unwrap().parent() {
|
||||
parent.write().unwrap().remove_child(node).unwrap();
|
||||
|
|
|
|||
|
|
@ -9,15 +9,33 @@ use crate::component::Component;
|
|||
use super::{insert, detach};
|
||||
|
||||
pub struct Rectangle {
|
||||
node: SharedNode,
|
||||
node: Arc<RwLock<primitives::Rectangle>>,
|
||||
attrs: RectangleAttributes
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RectangleAttributes {}
|
||||
pub struct RectangleAttributes {
|
||||
pub radius: f32
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PartialRectangleAttributes {
|
||||
pub radius: Option<f32>
|
||||
}
|
||||
|
||||
impl From<RectangleAttributes> for PartialRectangleAttributes {
|
||||
fn from(attrs: RectangleAttributes) ->
|
||||
Self {
|
||||
Self {
|
||||
radius: Some(attrs.radius)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Rectangle {
|
||||
type ComponentAttrs = RectangleAttributes;
|
||||
type PartialComponentAttrs = PartialRectangleAttributes;
|
||||
const UPDATE_LENGTH : usize = 1;
|
||||
fn new(attrs: Self::ComponentAttrs) -> Self {
|
||||
Self {
|
||||
node: Arc::new(RwLock::new(primitives::Rectangle {
|
||||
|
|
@ -32,22 +50,38 @@ impl Component for Rectangle {
|
|||
..Default::default()
|
||||
},
|
||||
fill: Paint::color(Color::rgb(0, 0, 255)),
|
||||
radius: 5.,
|
||||
radius: attrs.radius,
|
||||
..Default::default()
|
||||
})),
|
||||
attrs
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, attrs: Self::ComponentAttrs) { self.attrs = attrs; }
|
||||
fn set(&mut self, attrs: Self::PartialComponentAttrs) {
|
||||
let mut to_update = [0];
|
||||
if let Some(radius) = attrs.radius {
|
||||
self.attrs.radius = radius;
|
||||
to_update[0] |= 1;
|
||||
}
|
||||
if to_update[0] != 0 {
|
||||
self.update(&to_update);
|
||||
}
|
||||
}
|
||||
fn get(&self) -> &Self::ComponentAttrs { &self.attrs }
|
||||
|
||||
fn mount(&self, parent: &SharedNode, before: Option<&SharedNode>) {
|
||||
insert(parent, &self.node, before);
|
||||
insert(parent, &{self.node.clone()}, before);
|
||||
}
|
||||
|
||||
fn update(&self) {}
|
||||
fn update(&self, bitmap: &[u32]) {
|
||||
self.check_update(bitmap);
|
||||
|
||||
if bitmap[0] & 1 != 0 {
|
||||
self.node.write().unwrap().radius = self.attrs.radius;
|
||||
}
|
||||
}
|
||||
|
||||
fn unmount(&self) {
|
||||
detach(&self.node);
|
||||
detach(&{self.node.clone()});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue