mirror of
https://github.com/danbulant/mangui
synced 2026-06-19 06:11:21 +00:00
switch to signals, start working on slots
This commit is contained in:
parent
455fad5269
commit
d3cc64375a
12 changed files with 619 additions and 516 deletions
85
Cargo.lock
generated
85
Cargo.lock
generated
|
|
@ -163,9 +163,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.15.0"
|
||||
version = "3.15.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f"
|
||||
checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
|
|
@ -213,11 +213,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
]
|
||||
|
||||
|
|
@ -858,9 +857,9 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
|||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.6"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
|
||||
checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60"
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
|
|
@ -1022,15 +1021,6 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.3.1"
|
||||
|
|
@ -1124,9 +1114,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
|||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.12.2"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db2c024b41519440580066ba82aab04092b333e09066a5eb86c7c4890df31f22"
|
||||
checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
|
||||
|
||||
[[package]]
|
||||
name = "mangades"
|
||||
|
|
@ -1362,9 +1352,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.100"
|
||||
version = "0.9.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae94056a791d0e1217d18b6cbdccb02c61e3054fc69893607f4067e3bb0b1fd1"
|
||||
checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
|
@ -1640,6 +1630,7 @@ dependencies = [
|
|||
name = "rusalka-macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
|
|
@ -1906,12 +1897,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.5"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
|
||||
checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2558,7 +2549,7 @@ version = "0.52.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.0",
|
||||
"windows-targets 0.52.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2593,17 +2584,17 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.0",
|
||||
"windows_aarch64_msvc 0.52.0",
|
||||
"windows_i686_gnu 0.52.0",
|
||||
"windows_i686_msvc 0.52.0",
|
||||
"windows_x86_64_gnu 0.52.0",
|
||||
"windows_x86_64_gnullvm 0.52.0",
|
||||
"windows_x86_64_msvc 0.52.0",
|
||||
"windows_aarch64_gnullvm 0.52.3",
|
||||
"windows_aarch64_msvc 0.52.3",
|
||||
"windows_i686_gnu 0.52.3",
|
||||
"windows_i686_msvc 0.52.3",
|
||||
"windows_x86_64_gnu 0.52.3",
|
||||
"windows_x86_64_gnullvm 0.52.3",
|
||||
"windows_x86_64_msvc 0.52.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2620,9 +2611,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
|
|
@ -2638,9 +2629,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
|
@ -2656,9 +2647,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
|
|
@ -2674,9 +2665,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
|
|
@ -2692,9 +2683,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
|
|
@ -2710,9 +2701,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
|
@ -2728,9 +2719,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
|
||||
|
||||
[[package]]
|
||||
name = "winit"
|
||||
|
|
|
|||
|
|
@ -5,12 +5,9 @@ use mangui::nodes::TaffyStyle;
|
|||
use mangui::taffy::Display::Block;
|
||||
use mangui::taffy::{FlexDirection, LengthPercentage, Rect};
|
||||
|
||||
use rusalka::nodes::primitives::{Rectangle, RectangleAttributes, PartialRectangleAttributes};
|
||||
|
||||
make_component!(
|
||||
ComponentDemo,
|
||||
MainLogic {
|
||||
let _radius = attrs.radius;
|
||||
let imgpath = std::path::PathBuf::from("./demo/large/bx117324-97mHyfJGwpBq.jpg");
|
||||
let imgflags = ImageFlags::empty();
|
||||
let width = 230.;
|
||||
|
|
@ -23,13 +20,11 @@ make_component!(
|
|||
test_: bool = false
|
||||
}
|
||||
Reactive {
|
||||
// dbg!($test_);
|
||||
println!("reactive block");
|
||||
println!("test_ = {}", $test_);
|
||||
}
|
||||
Component {
|
||||
@layout {
|
||||
@Rectangle {
|
||||
radius: if $test_ { attrs.radius } else { 0. }
|
||||
}
|
||||
@layout {
|
||||
@text {
|
||||
text: String::from("Hello, World 🌎! And there's more text in here, as a single line"),
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use mangui::{self, nodes::layout::Layout, SharedNode, MainEntry};
|
|||
|
||||
mod component_demo_syntax;
|
||||
mod anilist;
|
||||
mod slot_demo;
|
||||
|
||||
use rusalka::component::Component;
|
||||
|
||||
|
|
|
|||
266
mangades/src/slot_demo.rs
Normal file
266
mangades/src/slot_demo.rs
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use mangui::nodes::layout::Layout;
|
||||
use mangui::nodes::primitives::Rectangle;
|
||||
use rusalka::component::Slot;
|
||||
use rusalka::store::{DerefGuardExt, ReadableStore, Signal, StoreUnsubscribe, Writable, WritableStore};
|
||||
|
||||
pub struct SlotAcceptDemo {
|
||||
comp0: rusalka::SharedNodeComponent<Layout>,
|
||||
comp1: Mutex<Option<Slot>>,
|
||||
selfref: rusalka::WeakSharedComponent<Self>,
|
||||
attrs: ReactiveSlotAcceptDemoAttributes,
|
||||
}
|
||||
|
||||
type SlotArgs = ();
|
||||
type DSlot = Option<Mutex<Box<dyn FnMut(SlotArgs) -> Slot>>>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SlotAcceptDemoAttributes {
|
||||
pub __default_slot: DSlot
|
||||
}
|
||||
|
||||
pub struct ReactiveSlotAcceptDemoAttributes {
|
||||
__default_slot: DSlot
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PartialSlotAcceptDemoAttributes {
|
||||
pub __default_slot: Option<DSlot>
|
||||
}
|
||||
impl From<SlotAcceptDemoAttributes> for PartialSlotAcceptDemoAttributes {
|
||||
fn from(attrs: SlotAcceptDemoAttributes) -> Self {
|
||||
Self { __default_slot: Some(attrs.__default_slot) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SlotAcceptDemoAttributes> for ReactiveSlotAcceptDemoAttributes {
|
||||
fn from(attrs: SlotAcceptDemoAttributes) -> Self {
|
||||
Self { __default_slot: attrs.__default_slot }
|
||||
}
|
||||
}
|
||||
|
||||
impl rusalka::component::Component for SlotAcceptDemo {
|
||||
type ComponentAttrs = SlotAcceptDemoAttributes;
|
||||
type ReactiveComponentAttrs = ReactiveSlotAcceptDemoAttributes;
|
||||
type PartialComponentAttrs = PartialSlotAcceptDemoAttributes;
|
||||
const UPDATE_LENGTH: usize = 1;
|
||||
fn new(
|
||||
attrs: Self::ComponentAttrs,
|
||||
selfref: rusalka::WeakSharedComponent<Self>,
|
||||
) -> Self {
|
||||
let this = Self {
|
||||
comp0: std::sync::Arc::new(
|
||||
std::sync::RwLock::new(Layout { ..Default::default() }),
|
||||
),
|
||||
comp1: Mutex::new(None),
|
||||
attrs: attrs.into(),
|
||||
selfref
|
||||
};
|
||||
this
|
||||
}
|
||||
fn set(&mut self, attrs: Self::PartialComponentAttrs) {
|
||||
|
||||
}
|
||||
fn get(&self) -> &Self::ReactiveComponentAttrs {
|
||||
&self.attrs
|
||||
}
|
||||
fn mount(
|
||||
&self,
|
||||
parent: &mangui::SharedNode,
|
||||
before: Option<&mangui::SharedNode>,
|
||||
) {
|
||||
rusalka::nodes::insert(parent, &{ self.comp0.clone() }, before);
|
||||
match &self.attrs.__default_slot {
|
||||
Some(slot) => {
|
||||
*self.comp1.lock().unwrap() = Some(slot.lock().unwrap()(()));
|
||||
(*self.comp1.lock().unwrap().as_mut().unwrap().mount)(parent, before);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
fn unmount(&self) {
|
||||
rusalka::nodes::detach(&{ self.comp0.clone() });
|
||||
match &self.attrs.__default_slot {
|
||||
Some(slot) => {
|
||||
(*self.comp1.lock().unwrap().as_mut().unwrap().unmount)();
|
||||
*self.comp1.lock().unwrap() = None;
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SlotDemoSlot1 {
|
||||
comp0: rusalka::SharedNodeComponent<Rectangle>,
|
||||
sub0: Box<dyn StoreUnsubscribe>
|
||||
}
|
||||
|
||||
pub struct SlotDemo {
|
||||
comp0: rusalka::SharedNodeComponent<Layout>,
|
||||
comp1: rusalka::SharedComponent<SlotAcceptDemo>,
|
||||
test_: std::sync::Arc<std::sync::Mutex<rusalka::store::Writable<bool>>>,
|
||||
sub0: Box<dyn StoreUnsubscribe>,
|
||||
selfref: rusalka::WeakSharedComponent<Self>,
|
||||
attrs: ReactiveSlotDemoAttributes,
|
||||
}
|
||||
#[derive(Default)]
|
||||
pub struct SlotDemoAttributes {
|
||||
pub test: f32
|
||||
}
|
||||
|
||||
pub struct ReactiveSlotDemoAttributes {
|
||||
pub test: Arc<Mutex<Writable<f32>>>
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PartialSlotDemoAttributes {
|
||||
pub test: Option<f32>
|
||||
}
|
||||
impl From<SlotDemoAttributes> for PartialSlotDemoAttributes {
|
||||
fn from(attrs: SlotDemoAttributes) -> Self {
|
||||
Self { test: Some(attrs.test) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ReactiveSlotDemoAttributes> for SlotDemoAttributes {
|
||||
fn from(attrs: ReactiveSlotDemoAttributes) -> Self {
|
||||
Self { test: *attrs.test.lock().unwrap().get() }
|
||||
}
|
||||
}
|
||||
impl From<&ReactiveSlotDemoAttributes> for SlotDemoAttributes {
|
||||
fn from(attrs: &ReactiveSlotDemoAttributes) -> Self {
|
||||
Self { test: *attrs.test.lock().unwrap().get() }
|
||||
}
|
||||
}
|
||||
impl From<SlotDemoAttributes> for ReactiveSlotDemoAttributes {
|
||||
fn from(attrs: SlotDemoAttributes) -> Self {
|
||||
Self { test: Arc::new(Mutex::new(Writable::new(attrs.test))) }
|
||||
}
|
||||
}
|
||||
|
||||
impl rusalka::component::Component for SlotDemo {
|
||||
type ComponentAttrs = SlotDemoAttributes;
|
||||
type ReactiveComponentAttrs = ReactiveSlotDemoAttributes;
|
||||
type PartialComponentAttrs = PartialSlotDemoAttributes;
|
||||
const UPDATE_LENGTH: usize = 1;
|
||||
fn new(
|
||||
attrs: Self::ComponentAttrs,
|
||||
selfref: rusalka::WeakSharedComponent<Self>,
|
||||
) -> Self {
|
||||
let attrs: Self::ReactiveComponentAttrs = attrs.into();
|
||||
let test_: std::sync::Arc<
|
||||
std::sync::Mutex<rusalka::store::Writable<bool>>,
|
||||
> = std::sync::Arc::new(
|
||||
std::sync::Mutex::new(rusalka::store::Writable::new(false)),
|
||||
);
|
||||
let test = attrs.test.clone();
|
||||
let this = Self {
|
||||
comp0: std::sync::Arc::new(
|
||||
std::sync::RwLock::new(Layout { ..Default::default() }),
|
||||
),
|
||||
comp1: std::sync::Arc::new_cyclic(|cselfref2| std::sync::Mutex::new(
|
||||
SlotAcceptDemo::new(
|
||||
SlotAcceptDemoAttributes {
|
||||
__default_slot: Some(Mutex::new(Box::new(move |_| {
|
||||
let comp0: Arc<Mutex<Option<SlotDemoSlot1>>> = Arc::new(Mutex::new(None));
|
||||
Slot {
|
||||
mount: {
|
||||
let comp0 = comp0.clone();
|
||||
let test = test.clone();
|
||||
Box::new(move |parent, before| {
|
||||
if let None = comp0.lock().unwrap().as_ref() {
|
||||
let slot = Some(
|
||||
SlotDemoSlot1 {
|
||||
comp0: std::sync::Arc::new(
|
||||
std::sync::RwLock::new(Rectangle { radius: *test.clone().lock().unwrap().get(), ..Default::default() }),
|
||||
),
|
||||
sub0: {
|
||||
let comp0 = comp0.clone();
|
||||
let test = test.clone();
|
||||
[test.clone().lock().unwrap()].subscribe(Box::new(move || {
|
||||
let comp1 = comp0.clone();
|
||||
let test1 = test.clone();
|
||||
let mut comp1l = comp1.lock().unwrap();
|
||||
if let Some(comp1) = comp1l.as_mut() {
|
||||
comp1.comp0.write().unwrap().radius = *test1.lock().unwrap().get();
|
||||
}
|
||||
}))
|
||||
},
|
||||
}
|
||||
);
|
||||
*comp0.lock().unwrap() = slot;
|
||||
}
|
||||
rusalka::nodes::insert(parent, &{ comp0.lock().as_ref().unwrap().as_ref().unwrap().comp0.clone() }, before);
|
||||
})
|
||||
},
|
||||
unmount: {
|
||||
let comp0 = comp0.clone();
|
||||
Box::new(move || {
|
||||
let comp0 = comp0.clone();
|
||||
if let Some(comp0) = comp0.lock().unwrap().as_mut() {
|
||||
rusalka::nodes::detach(&{ comp0.comp0.clone() });
|
||||
}
|
||||
*comp0.lock().unwrap() = None;
|
||||
})
|
||||
},
|
||||
}
|
||||
})))
|
||||
},
|
||||
cselfref2.clone(),
|
||||
),
|
||||
)),
|
||||
sub0: {
|
||||
let test = test_.clone();
|
||||
[test.clone().lock().unwrap()].subscribe(Box::new(move || {
|
||||
let test = test.clone();
|
||||
dbg!(test.lock().unwrap().get());
|
||||
}))
|
||||
},
|
||||
attrs,
|
||||
selfref,
|
||||
test_
|
||||
};
|
||||
let selfref = this.selfref.clone();
|
||||
this.comp0
|
||||
.write()
|
||||
.unwrap()
|
||||
.events
|
||||
.add_handler(
|
||||
Box::new(move |event| {
|
||||
let selfref = selfref.upgrade().unwrap();
|
||||
let mut this = selfref.lock().unwrap();
|
||||
let attrs = &this.attrs;
|
||||
let test_ = &this.test_;
|
||||
match event.event {
|
||||
mangui::events::InnerEvent::MouseDown(_) => {
|
||||
**test_.lock().unwrap().guard() = true;
|
||||
}
|
||||
mangui::events::InnerEvent::MouseUp(_) => {
|
||||
**test_.lock().unwrap().guard() = false;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}),
|
||||
);
|
||||
this
|
||||
}
|
||||
fn set(&mut self, attrs: Self::PartialComponentAttrs) {
|
||||
if let Some(test) = attrs.test {
|
||||
**self.attrs.test.lock().unwrap().guard() = test;
|
||||
// self.attrs.test.lock().unwrap().set(test);
|
||||
}
|
||||
}
|
||||
fn get(&self) -> &Self::ReactiveComponentAttrs {
|
||||
&self.attrs
|
||||
}
|
||||
fn mount(
|
||||
&self,
|
||||
parent: &mangui::SharedNode,
|
||||
before: Option<&mangui::SharedNode>,
|
||||
) {
|
||||
rusalka::nodes::insert(parent, &{ self.comp0.clone() }, before);
|
||||
}
|
||||
fn unmount(&self) {
|
||||
rusalka::nodes::detach(&{ self.comp0.clone() });
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ authors.workspace = true
|
|||
|
||||
[dependencies]
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0.78"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
use proc_macro2::{Ident, TokenStream, TokenTree, Span, Group, Delimiter};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use proc_macro::{TokenStream, TokenTree, Ident, Group, Span, Literal};
|
||||
use quote::quote;
|
||||
use quote::{format_ident, quote, ToTokens};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Attribute {
|
||||
|
|
@ -51,7 +51,8 @@ struct ReactiveBlock {
|
|||
|
||||
#[proc_macro]
|
||||
/// If you have syntax errors because of attributes, wrap the default value in parentheses.
|
||||
pub fn make_component(item: TokenStream) -> TokenStream {
|
||||
pub fn make_component(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let item = TokenStream::from(item);
|
||||
let mut last_identifier = None;
|
||||
let mut item = item.into_iter();
|
||||
let name = item.next().unwrap();
|
||||
|
|
@ -201,11 +202,13 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
},
|
||||
"Reactive" => {
|
||||
let (variables, contents) = replace_variables(group.stream());
|
||||
reactive_blocks.push(ReactiveBlock {
|
||||
variables,
|
||||
contents,
|
||||
prop_ident: None
|
||||
});
|
||||
if !contents.is_empty() && !variables.is_empty() {
|
||||
reactive_blocks.push(ReactiveBlock {
|
||||
variables,
|
||||
contents,
|
||||
prop_ident: None
|
||||
});
|
||||
}
|
||||
},
|
||||
"Component" => {
|
||||
// Example syntax:
|
||||
|
|
@ -268,25 +271,28 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
let mut output = TokenStream::new();
|
||||
|
||||
// Component struct
|
||||
output.extend(quote!(
|
||||
use rusalka::store::DerefGuardExt;
|
||||
use rusalka::store::WritableStore;
|
||||
use rusalka::store::Signal;
|
||||
));
|
||||
|
||||
output.extend(TokenStream::from(quote!(pub struct)));
|
||||
output.extend(quote!(pub struct));
|
||||
output.extend(Some(TokenTree::Ident(name_ident.clone())));
|
||||
|
||||
let mut component_struct_stream = TokenStream::new();
|
||||
|
||||
let mut i = 0;
|
||||
for component in &components_used {
|
||||
|
||||
for (i, component) in components_used.iter().enumerate() {
|
||||
let ident = Ident::new(&format!("comp{}", i), component.name.span());
|
||||
|
||||
let mut midstream = TokenStream::from(quote!(: rusalka::));
|
||||
let mut midstream = quote!(: rusalka::);
|
||||
|
||||
match component.component_type {
|
||||
ComponentType::RealComponent => {
|
||||
midstream.extend(TokenStream::from(quote!(SharedComponent<)));
|
||||
midstream.extend(quote!(SharedComponent<));
|
||||
},
|
||||
ComponentType::Node => {
|
||||
midstream.extend(TokenStream::from(quote!(SharedNodeComponent<)));
|
||||
midstream.extend(quote!(SharedNodeComponent<));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -295,15 +301,22 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
component_struct_stream.extend(Some(TokenTree::Ident(ident)));
|
||||
component_struct_stream.extend(midstream);
|
||||
component_struct_stream.extend(Some(TokenTree::Ident(component_name)));
|
||||
component_struct_stream.extend(TokenStream::from(quote!(>,)));
|
||||
component_struct_stream.extend(quote!(>,));
|
||||
}
|
||||
|
||||
let mut i = 0u32;
|
||||
for block in &reactive_blocks {
|
||||
let ident = format_ident!("sub{}", i);
|
||||
component_struct_stream.extend(quote!(
|
||||
#ident: Box<dyn rusalka::store::StoreUnsubscribe>,
|
||||
));
|
||||
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!(std::sync::Arc<std::sync::Mutex<rusalka::invalidator::Invalidator<)));
|
||||
component_struct_stream.extend(TokenStream::from(quote!(std::sync::Arc<std::sync::Mutex<rusalka::store::Writable<)));
|
||||
component_struct_stream.extend(variable.type_.clone());
|
||||
component_struct_stream.extend(TokenStream::from(quote!(>>>)));
|
||||
component_struct_stream.extend(TokenStream::from(quote!(,)));
|
||||
|
|
@ -316,11 +329,13 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
// Attributes struct
|
||||
|
||||
let attributes_ident = Ident::new(&format!("{str_name}Attributes"), name_ident.span());
|
||||
let partial_attributes_ident = Ident::new(&format!("Partial{str_name}Attributes"), name_ident.span());
|
||||
let reactive_attributes_ident = Ident::new(&format!("Reactive{str_name}Attributes"), name_ident.span());
|
||||
|
||||
component_struct_stream.extend(TokenStream::from(quote!(attrs: )));
|
||||
component_struct_stream.extend(Some(TokenTree::Ident(attributes_ident.clone())));
|
||||
component_struct_stream.extend(Some(TokenTree::Ident(reactive_attributes_ident.clone())));
|
||||
|
||||
let component_struct_group = Group::new(proc_macro::Delimiter::Brace, component_struct_stream);
|
||||
let component_struct_group = Group::new(proc_macro2::Delimiter::Brace, component_struct_stream);
|
||||
output.extend(Some(TokenTree::Group(component_struct_group)));
|
||||
|
||||
|
||||
|
|
@ -338,11 +353,10 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
attributes_struct_stream.extend(TokenStream::from(quote!(,)));
|
||||
}
|
||||
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, attributes_struct_stream))));
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro2::Delimiter::Brace, attributes_struct_stream))));
|
||||
|
||||
// partial attributes
|
||||
|
||||
let partial_attributes_ident = Ident::new(&format!("Partial{str_name}Attributes"), name_ident.span());
|
||||
output.extend(TokenStream::from(quote!(#[derive(Default)] pub struct)));
|
||||
output.extend(Some(TokenTree::Ident(partial_attributes_ident.clone())));
|
||||
let mut attributes_default_struct_stream = TokenStream::new();
|
||||
|
|
@ -355,7 +369,23 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
attributes_default_struct_stream.extend(TokenStream::from(quote!(>,)));
|
||||
}
|
||||
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, attributes_default_struct_stream))));
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro2::Delimiter::Brace, attributes_default_struct_stream))));
|
||||
|
||||
// reactive attributes
|
||||
|
||||
output.extend(TokenStream::from(quote!(#[derive(Default)] pub struct)));
|
||||
output.extend(Some(TokenTree::Ident(reactive_attributes_ident.clone())));
|
||||
let mut attributes_default_struct_stream = TokenStream::new();
|
||||
|
||||
for attribute in &attributes {
|
||||
attributes_default_struct_stream.extend(TokenStream::from(quote!(pub)));
|
||||
attributes_default_struct_stream.extend(Some(TokenTree::Ident(attribute.name.clone())));
|
||||
attributes_default_struct_stream.extend(TokenStream::from(quote!(: std::sync::Arc<std::sync::Mutex<rusalka::store::Writable<)));
|
||||
attributes_default_struct_stream.extend(attribute.type_.clone());
|
||||
attributes_default_struct_stream.extend(TokenStream::from(quote!(>>>,)));
|
||||
}
|
||||
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro2::Delimiter::Brace, attributes_default_struct_stream))));
|
||||
|
||||
// impl From<Attributes> for PartialAttributes
|
||||
|
||||
|
|
@ -371,7 +401,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
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(Some(TokenTree::Group(Group::new(proc_macro2::Delimiter::Parenthesis, from_args))));
|
||||
from_stream.extend(TokenStream::from(quote!(-> Self)));
|
||||
|
||||
let mut from_fn_stream = TokenStream::from(quote!(Self));
|
||||
|
|
@ -388,57 +418,91 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
from_fn_stream_inner_inner.extend(TokenStream::from(quote!(attrs.)));
|
||||
from_fn_stream_inner_inner.extend(Some(TokenTree::Ident(attribute.name.clone())));
|
||||
|
||||
from_fn_stream_inner.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Parenthesis, from_fn_stream_inner_inner))));
|
||||
from_fn_stream_inner.extend(Some(TokenTree::Group(Group::new(Delimiter::Parenthesis, from_fn_stream_inner_inner))));
|
||||
}
|
||||
|
||||
from_fn_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, from_fn_stream_inner))));
|
||||
from_fn_stream.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, from_fn_stream_inner))));
|
||||
|
||||
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))));
|
||||
from_stream.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, from_fn_stream))));
|
||||
output.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, from_stream))));
|
||||
|
||||
// impl From<Attributes> for ReactiveAttributes
|
||||
|
||||
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(reactive_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(Delimiter::Parenthesis, from_args))));
|
||||
from_stream.extend(TokenStream::from(quote!(-> Self)));
|
||||
|
||||
let mut from_fn_stream = TokenStream::from(quote!(Self));
|
||||
|
||||
let mut from_fn_stream_inner = TokenStream::new();
|
||||
|
||||
for attribute in &attributes {
|
||||
let name = attribute.name.clone();
|
||||
from_fn_stream_inner.extend(TokenStream::from(quote!(
|
||||
#name : std::sync::Arc::new(std::sync::Mutex::new(rusalka::store::Writable::new(attrs.#name)))
|
||||
)));
|
||||
}
|
||||
|
||||
from_fn_stream.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, from_fn_stream_inner))));
|
||||
|
||||
from_stream.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, from_fn_stream))));
|
||||
output.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, from_stream))));
|
||||
|
||||
// Component impl
|
||||
|
||||
output.extend(TokenStream::from(quote!(impl rusalka::component::Component for)));
|
||||
output.extend(Some(TokenTree::Ident(name_ident.clone())));
|
||||
output.extend(TokenStream::from(quote!(impl rusalka::component::Component for #name_ident)));
|
||||
|
||||
let mut component_impl_stream = TokenStream::new();
|
||||
|
||||
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!(;)));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(const UPDATE_LENGTH : usize =)));
|
||||
component_impl_stream.extend(Some(TokenTree::Literal(Literal::usize_unsuffixed(f64::ceil((attributes.len() + reactive_variables.len()) as f64 / 32 as f64) as usize))));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(;)));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(
|
||||
type ComponentAttrs = #attributes_ident;
|
||||
type PartialComponentAttrs = #partial_attributes_ident;
|
||||
type ReactiveComponentAttrs = #reactive_attributes_ident;
|
||||
)));
|
||||
|
||||
// fn new
|
||||
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn new(attrs: Self::ComponentAttrs, selfref: rusalka::WeakSharedComponent<Self>) -> Self)));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(
|
||||
fn new(attrs: Self::ComponentAttrs, selfref: rusalka::WeakSharedComponent<Self>) -> Self
|
||||
)));
|
||||
|
||||
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!(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!(=)));
|
||||
new_stream.extend(TokenStream::from(quote!(
|
||||
let attrs: Self::ReactiveComponentAttrs = attrs.into();
|
||||
)));
|
||||
|
||||
let mut invalidator = TokenStream::from(quote!(rusalka::invalidator::Invalidator::new));
|
||||
for attribute in &attributes {
|
||||
let name = attribute.name.clone();
|
||||
new_stream.extend(TokenStream::from(quote!(
|
||||
let #name = attrs.#name.clone();
|
||||
)));
|
||||
}
|
||||
|
||||
for variable in &reactive_variables {
|
||||
let name = variable.name.clone();
|
||||
let type_ = variable.type_.clone();
|
||||
let mut invalidator_inner = TokenStream::new();
|
||||
if let Some(def) = &variable.default {
|
||||
invalidator_inner.extend(replace_variables(def.clone()).1);
|
||||
} 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(TokenStream::from(quote!(
|
||||
let #name : std::sync::Arc<std::sync::Mutex<rusalka::store::Writable< #type_ >>> =
|
||||
std::sync::Arc::new(std::sync::Mutex::new(rusalka::store::Writable::new( #invalidator_inner )));
|
||||
)));
|
||||
}
|
||||
|
||||
new_stream.extend(main_logic);
|
||||
|
|
@ -466,20 +530,20 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
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::Punct(Punct::new('<', 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), component_name.span()))));
|
||||
|
||||
let (_reactive_variables, subcomponent_stream) = replace_variables(component.contents.clone());
|
||||
let components_attributes_group = Group::new(proc_macro::Delimiter::Brace, subcomponent_stream);
|
||||
let components_attributes_group = Group::new(Delimiter::Brace, subcomponent_stream);
|
||||
|
||||
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(Delimiter::Parenthesis, component_new_stream);
|
||||
|
||||
component_stream.extend(Some(TokenTree::Group(component_new_group)));
|
||||
|
||||
|
|
@ -487,27 +551,44 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
},
|
||||
ComponentType::Node => {
|
||||
let (_reactive_variables, subcomponent_stream) = replace_variables(component.contents.clone());
|
||||
let node_group = Group::new(proc_macro::Delimiter::Brace, subcomponent_stream);
|
||||
let node_group = Group::new(Delimiter::Brace, subcomponent_stream);
|
||||
component_stream.extend(Some(TokenTree::Group(node_group)));
|
||||
new_returnvalue_stream.extend(wrap_in_arcrwlock(component_stream));
|
||||
}
|
||||
}
|
||||
new_returnvalue_stream.extend(TokenStream::from(quote!(,)));
|
||||
new_returnvalue_stream.extend(quote!(,));
|
||||
|
||||
i+=1;
|
||||
}
|
||||
|
||||
new_returnvalue_stream.extend(TokenStream::from(quote!(attrs, selfref,)));
|
||||
new_returnvalue_stream.extend(quote!(attrs, selfref,));
|
||||
|
||||
let mut i = 0u32;
|
||||
for reactive_block in &reactive_blocks {
|
||||
let ident = format_ident!("sub{}", i);
|
||||
let content = &reactive_block.contents;
|
||||
let variables = &reactive_block.variables;
|
||||
new_returnvalue_stream.extend(quote!(
|
||||
#ident: {
|
||||
#(let #variables = #variables.clone();)*
|
||||
[#(#variables.clone().lock().unwrap()),*].subscribe(Box::new(move || {
|
||||
#(let #variables = #variables.clone();)*
|
||||
#content
|
||||
}))
|
||||
},
|
||||
));
|
||||
i+=1;
|
||||
}
|
||||
|
||||
for variable in &reactive_variables {
|
||||
new_returnvalue_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||
new_returnvalue_stream.extend(TokenStream::from(quote!(,)));
|
||||
new_returnvalue_stream.extend(quote!(,));
|
||||
}
|
||||
|
||||
let new_returnvalue_group = Group::new(proc_macro::Delimiter::Brace, new_returnvalue_stream);
|
||||
let new_returnvalue_group = Group::new(Delimiter::Brace, new_returnvalue_stream);
|
||||
new_stream.extend(Some(TokenTree::Group(new_returnvalue_group)));
|
||||
|
||||
new_stream.extend(TokenStream::from(quote!(;)));
|
||||
new_stream.extend(quote!(;));
|
||||
|
||||
i = 0;
|
||||
for component in &components_used {
|
||||
|
|
@ -551,17 +632,15 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
inner_callback_stream.extend(replace_variables(event_listener.callback.clone().stream()).1);
|
||||
|
||||
inner_callback_stream.extend(TokenStream::from(quote!(this.tick(None);)));
|
||||
|
||||
let callback_group = Group::new(proc_macro::Delimiter::Brace, inner_callback_stream);
|
||||
let callback_group = Group::new(Delimiter::Brace, inner_callback_stream);
|
||||
|
||||
callback_stream.extend(Some(TokenTree::Group(callback_group)));
|
||||
|
||||
let callback_group = Group::new(proc_macro::Delimiter::Parenthesis, callback_stream);
|
||||
let callback_group = Group::new(Delimiter::Parenthesis, callback_stream);
|
||||
|
||||
box_stream.extend(Some(TokenTree::Group(callback_group)));
|
||||
|
||||
let box_group = Group::new(proc_macro::Delimiter::Parenthesis, box_stream);
|
||||
let box_group = Group::new(Delimiter::Parenthesis, box_stream);
|
||||
|
||||
new_stream.extend(Some(TokenTree::Group(box_group)));
|
||||
|
||||
|
|
@ -572,7 +651,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
new_stream.extend(TokenStream::from(quote!(this)));
|
||||
|
||||
let new_group = Group::new(proc_macro::Delimiter::Brace, new_stream);
|
||||
let new_group = Group::new(Delimiter::Brace, new_stream);
|
||||
component_impl_stream.extend(Some(TokenTree::Group(new_group)));
|
||||
|
||||
// fn set
|
||||
|
|
@ -581,14 +660,13 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
let mut set_stream = TokenStream::new();
|
||||
|
||||
if attributes.len() > 0 {
|
||||
set_stream.extend(TokenStream::from(quote!(let mut to_update = [0; Self::UPDATE_LENGTH];)));
|
||||
for (i, attribute) in attributes.iter().enumerate() {
|
||||
set_stream.extend(TokenStream::from(quote!(if let Some)));
|
||||
|
||||
let mut some_inner = TokenStream::new();
|
||||
some_inner.extend(Some(TokenTree::Ident(attribute.name.clone())));
|
||||
|
||||
set_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Parenthesis, some_inner))));
|
||||
set_stream.extend(Some(TokenTree::Group(Group::new(Delimiter::Parenthesis, some_inner))));
|
||||
|
||||
set_stream.extend(TokenStream::from(quote!(= attrs.)));
|
||||
set_stream.extend(Some(TokenTree::Ident(attribute.name.clone())));
|
||||
|
|
@ -597,31 +675,25 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
set_stream_inner.extend(TokenStream::from(quote!(self.attrs.)));
|
||||
set_stream_inner.extend(Some(TokenTree::Ident(attribute.name.clone())));
|
||||
set_stream_inner.extend(TokenStream::from(quote!(=)));
|
||||
set_stream_inner.extend(Some(TokenTree::Ident(attribute.name.clone())));
|
||||
set_stream_inner.extend(TokenStream::from(quote!(; to_update)));
|
||||
set_stream_inner.extend(TokenStream::from(quote!(.lock().unwrap().set)));
|
||||
|
||||
let mut to_update_stream = TokenStream::new();
|
||||
let mut set_stream_inner_inner = TokenStream::new();
|
||||
|
||||
to_update_stream.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(i as u32 / 32))));
|
||||
set_stream_inner_inner.extend(Some(TokenTree::Ident(attribute.name.clone())));
|
||||
|
||||
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(Delimiter::Parenthesis, set_stream_inner_inner))));
|
||||
set_stream_inner.extend(TokenStream::from(quote!(;)));
|
||||
|
||||
set_stream_inner.extend(TokenStream::from(quote!(|= )));
|
||||
set_stream_inner.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(1 << (i as u32 % 32)))));
|
||||
|
||||
set_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, set_stream_inner))));
|
||||
set_stream.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, set_stream_inner))));
|
||||
}
|
||||
|
||||
set_stream.extend(TokenStream::from(quote!(if to_update.into_iter().reduce(|a,b| a+b).unwrap() != 0 { self.tick(Some(&to_update)); })));
|
||||
}
|
||||
|
||||
|
||||
component_impl_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, set_stream))));
|
||||
component_impl_stream.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, set_stream))));
|
||||
|
||||
// fn get
|
||||
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn get(&self) -> &Self::ComponentAttrs { &self.attrs })));
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn get(&self) -> &Self::ReactiveComponentAttrs { &self.attrs })));
|
||||
|
||||
// fn mount
|
||||
|
||||
|
|
@ -652,7 +724,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
node_insert_self_stream.extend(Some(TokenTree::Ident(parent_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);
|
||||
let node_insert_self_group = Group::new(Delimiter::Brace, node_insert_self_stream);
|
||||
component_mount_stream.extend(TokenStream::from(quote!(&)));
|
||||
component_mount_stream.extend(Some(TokenTree::Group(node_insert_self_group)));
|
||||
},
|
||||
|
|
@ -663,7 +735,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
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);
|
||||
let component_mount_group = Group::new(Delimiter::Parenthesis, component_mount_stream);
|
||||
|
||||
mount_stream.extend(Some(TokenTree::Group(component_mount_group)));
|
||||
|
||||
|
|
@ -686,7 +758,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
node_insert_self_stream.extend(Some(TokenTree::Ident(parent_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);
|
||||
let node_insert_self_group = Group::new(Delimiter::Brace, node_insert_self_stream);
|
||||
node_insert_stream.extend(TokenStream::from(quote!(&)));
|
||||
node_insert_stream.extend(Some(TokenTree::Group(node_insert_self_group)));
|
||||
},
|
||||
|
|
@ -704,13 +776,13 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
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);
|
||||
let node_insert_self_group = Group::new(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))));
|
||||
node_stream.extend(Some(TokenTree::Group(Group::new(Delimiter::Parenthesis, node_insert_stream))));
|
||||
|
||||
mount_stream.extend(node_stream);
|
||||
mount_stream.extend(TokenStream::from(quote!(;)));
|
||||
|
|
@ -719,7 +791,7 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
|
||||
}
|
||||
|
||||
let mount_group = Group::new(proc_macro::Delimiter::Brace, mount_stream);
|
||||
let mount_group = Group::new(Delimiter::Brace, mount_stream);
|
||||
component_impl_stream.extend(Some(TokenTree::Group(mount_group)));
|
||||
|
||||
// fn unmount
|
||||
|
|
@ -755,219 +827,29 @@ pub fn make_component(item: TokenStream) -> TokenStream {
|
|||
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);
|
||||
let node_detach_self_group = Group::new(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);
|
||||
let node_detach_group = Group::new(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);
|
||||
let unmount_group = Group::new(Delimiter::Brace, unmount_stream);
|
||||
component_impl_stream.extend(Some(TokenTree::Group(unmount_group)));
|
||||
|
||||
// fn update
|
||||
|
||||
let mut all_variables = Vec::new();
|
||||
all_variables.extend(attributes.clone());
|
||||
all_variables.extend(reactive_variables.clone());
|
||||
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn update(&self, bitmap: &[u32]))));
|
||||
let mut update_stream = TokenStream::new();
|
||||
update_stream.extend(TokenStream::from(quote!(
|
||||
self.check_update(bitmap);
|
||||
let attrs = &self.attrs;
|
||||
)));
|
||||
|
||||
for variable in &reactive_variables {
|
||||
update_stream.extend(TokenStream::from(quote!(let)));
|
||||
update_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||
update_stream.extend(TokenStream::from(quote!(=)));
|
||||
update_stream.extend(TokenStream::from(quote!(&self.)));
|
||||
update_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||
update_stream.extend(TokenStream::from(quote!(;)));
|
||||
}
|
||||
|
||||
'block: for block in &reactive_blocks {
|
||||
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, str_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;
|
||||
}
|
||||
if keys.iter().all(|x| *x == 0) {
|
||||
continue 'block;
|
||||
}
|
||||
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 inner_group = Group::new(proc_macro::Delimiter::Brace, block.contents.clone());
|
||||
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, str_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 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), component.name.span()))));
|
||||
|
||||
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);
|
||||
component_impl_stream.extend(Some(TokenTree::Group(update_group)));
|
||||
|
||||
|
||||
// fn tick
|
||||
|
||||
component_impl_stream.extend(TokenStream::from(quote!(fn tick(&mut self, inbitmap: Option<&[u32]>))));
|
||||
|
||||
let mut tick_stream = TokenStream::new();
|
||||
|
||||
tick_stream.extend(TokenStream::from(quote!(
|
||||
let mut bitmap = [0; Self::UPDATE_LENGTH];
|
||||
if let Some(inbitmap) = inbitmap {
|
||||
bitmap.clone_from_slice(inbitmap);
|
||||
}
|
||||
self.check_update(&bitmap);
|
||||
)));
|
||||
|
||||
let mut i = attributes.len() as u32;
|
||||
for variable in &reactive_variables {
|
||||
tick_stream.extend(TokenStream::from(quote!(if self.)));
|
||||
tick_stream.extend(Some(TokenTree::Ident(variable.name.clone())));
|
||||
tick_stream.extend(TokenStream::from(quote!(.lock().unwrap().invalidated())));
|
||||
|
||||
let mut if_stream = TokenStream::new();
|
||||
|
||||
let array_offset = i / 32;
|
||||
let num_offset = i % 32;
|
||||
|
||||
if_stream.extend(TokenStream::from(quote!(bitmap)));
|
||||
let mut ifgroup_stream = TokenStream::new();
|
||||
ifgroup_stream.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(array_offset))));
|
||||
if_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Bracket, ifgroup_stream))));
|
||||
if_stream.extend(TokenStream::from(quote!(|= )));
|
||||
if_stream.extend(Some(TokenTree::Literal(Literal::u32_unsuffixed(1 << num_offset))));
|
||||
|
||||
tick_stream.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, if_stream))));
|
||||
i += 1;
|
||||
}
|
||||
|
||||
tick_stream.extend(TokenStream::from(quote!(
|
||||
if bitmap.into_iter().reduce(|a, b| a + b).unwrap() != 0 {
|
||||
self.update(&bitmap);
|
||||
}
|
||||
)));
|
||||
|
||||
let tick_group = Group::new(proc_macro::Delimiter::Brace, tick_stream);
|
||||
component_impl_stream.extend(Some(TokenTree::Group(tick_group)));
|
||||
|
||||
output.extend(Some(TokenTree::Group(Group::new(proc_macro::Delimiter::Brace, component_impl_stream))));
|
||||
output.extend(Some(TokenTree::Group(Group::new(Delimiter::Brace, component_impl_stream))));
|
||||
|
||||
println!("{}", output.to_string());
|
||||
|
||||
println!();
|
||||
|
||||
output
|
||||
output.into()
|
||||
}
|
||||
|
||||
/// Replaces $variable with **variable.lock().unwrap()
|
||||
/// Replaces $variable with **variable.lock().unwrap().guard()
|
||||
/// Returns the found variables as well as tokenstream with replaced variables
|
||||
/// Returned vec is sorted and deduplicated
|
||||
fn replace_variables(stream: TokenStream) -> (Vec<Ident>, TokenStream) {
|
||||
|
|
@ -987,7 +869,7 @@ fn replace_variables(stream: TokenStream) -> (Vec<Ident>, TokenStream) {
|
|||
idents.push(ident.clone());
|
||||
output.extend(TokenStream::from(quote!(**)));
|
||||
output.extend(Some(TokenTree::Ident(ident.clone())));
|
||||
output.extend(TokenStream::from(quote!(.lock().unwrap())));
|
||||
output.extend(TokenStream::from(quote!(.lock().unwrap().guard())));
|
||||
},
|
||||
TokenTree::Group(group) => {
|
||||
let group_delim = group.delimiter();
|
||||
|
|
@ -1015,7 +897,7 @@ fn wrap_in_arc_mutex(stream: TokenStream) -> TokenStream {
|
|||
|
||||
output.extend(TokenStream::from(quote!(std::sync::Arc::new)));
|
||||
|
||||
let mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream);
|
||||
let mutex_group = Group::new(Delimiter::Parenthesis, stream);
|
||||
|
||||
let mut mutex_stream = TokenStream::new();
|
||||
|
||||
|
|
@ -1023,7 +905,7 @@ fn wrap_in_arc_mutex(stream: TokenStream) -> TokenStream {
|
|||
|
||||
mutex_stream.extend(Some(TokenTree::Group(mutex_group)));
|
||||
|
||||
let arc_group = Group::new(proc_macro::Delimiter::Parenthesis, mutex_stream);
|
||||
let arc_group = Group::new(Delimiter::Parenthesis, mutex_stream);
|
||||
|
||||
output.extend(Some(TokenTree::Group(arc_group)));
|
||||
|
||||
|
|
@ -1035,7 +917,7 @@ fn wrap_in_arcmutex_cyclic(stream: TokenStream) -> TokenStream {
|
|||
|
||||
output.extend(TokenStream::from(quote!(std::sync::Arc::new_cyclic)));
|
||||
|
||||
let mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream);
|
||||
let mutex_group = Group::new(Delimiter::Parenthesis, stream);
|
||||
|
||||
let mut mutex_stream = TokenStream::new();
|
||||
|
||||
|
|
@ -1045,7 +927,7 @@ fn wrap_in_arcmutex_cyclic(stream: TokenStream) -> TokenStream {
|
|||
|
||||
mutex_stream.extend(Some(TokenTree::Group(mutex_group)));
|
||||
|
||||
let arc_group = Group::new(proc_macro::Delimiter::Parenthesis, mutex_stream);
|
||||
let arc_group = Group::new(Delimiter::Parenthesis, mutex_stream);
|
||||
|
||||
output.extend(Some(TokenTree::Group(arc_group)));
|
||||
|
||||
|
|
@ -1057,7 +939,7 @@ fn wrap_in_arcrwlock(stream: TokenStream) -> TokenStream {
|
|||
|
||||
output.extend(TokenStream::from(quote!(std::sync::Arc::new)));
|
||||
|
||||
let mutex_group = Group::new(proc_macro::Delimiter::Parenthesis, stream);
|
||||
let mutex_group = Group::new(Delimiter::Parenthesis, stream);
|
||||
|
||||
let mut rwlock_stream = TokenStream::new();
|
||||
|
||||
|
|
@ -1065,7 +947,7 @@ fn wrap_in_arcrwlock(stream: TokenStream) -> TokenStream {
|
|||
|
||||
rwlock_stream.extend(Some(TokenTree::Group(mutex_group)));
|
||||
|
||||
let arc_group = Group::new(proc_macro::Delimiter::Parenthesis, rwlock_stream);
|
||||
let arc_group = Group::new(Delimiter::Parenthesis, rwlock_stream);
|
||||
|
||||
output.extend(Some(TokenTree::Group(arc_group)));
|
||||
|
||||
|
|
|
|||
|
|
@ -4,25 +4,18 @@ use crate::WeakSharedComponent;
|
|||
|
||||
/// A rusalka component
|
||||
pub trait Component {
|
||||
type ComponentAttrs: Default;
|
||||
type ComponentAttrs;
|
||||
type ReactiveComponentAttrs: From<Self::ComponentAttrs>;
|
||||
type PartialComponentAttrs: Default + From<Self::ComponentAttrs>;
|
||||
const UPDATE_LENGTH : usize = 0;
|
||||
fn new(attr: Self::ComponentAttrs, selfref: WeakSharedComponent<Self>) -> Self;
|
||||
fn get(&self) -> &Self::ComponentAttrs;
|
||||
fn get(&self) -> &Self::ReactiveComponentAttrs;
|
||||
fn set(&mut self, attr: Self::PartialComponentAttrs);
|
||||
fn mount(&self, parent: &SharedNode, before: Option<&SharedNode>);
|
||||
fn update(&self, bitmap: &[u32]);
|
||||
fn unmount(&self);
|
||||
fn tick(&mut self, bitmap: Option<&[u32]>) {
|
||||
if let Some(bitmap) = bitmap {
|
||||
self.update(bitmap);
|
||||
}
|
||||
}
|
||||
// fn set_selfref(&mut self, selfref: SharedComponent<Self>);
|
||||
|
||||
fn check_update(&self, bitmap: &[u32]) -> () {
|
||||
if bitmap.len() != Self::UPDATE_LENGTH {
|
||||
panic!("Bitmap length does not match update length");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Slot {
|
||||
pub mount: Box<dyn FnMut(&SharedNode, Option<&SharedNode>)>,
|
||||
pub unmount: Box<dyn FnMut()>,
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5,7 +5,6 @@ use mangui::nodes::Node;
|
|||
|
||||
pub mod component;
|
||||
pub mod nodes;
|
||||
pub mod invalidator;
|
||||
pub mod store;
|
||||
|
||||
pub type SharedComponent<T: Component> = Arc<Mutex<T>>;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
|
||||
// DemoComponent
|
||||
|
||||
use std::sync::{Arc, RwLock};
|
||||
use mangui::{SharedNode, nodes::{primitives, Style}, taffy::prelude::Size, femtovg::{Paint, Color}};
|
||||
|
||||
use crate::{component::Component, WeakSharedComponent};
|
||||
|
||||
use super::{insert, detach};
|
||||
|
||||
pub struct Rectangle {
|
||||
node: Arc<RwLock<primitives::Rectangle>>,
|
||||
attrs: RectangleAttributes,
|
||||
selfref: WeakSharedComponent<Self>
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
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, selfref: WeakSharedComponent<Self>) -> Self {
|
||||
Self {
|
||||
node: Arc::new(RwLock::new(primitives::Rectangle {
|
||||
style: Style {
|
||||
layout: mangui::nodes::TaffyStyle {
|
||||
min_size: Size {
|
||||
width: mangui::taffy::style::Dimension::Length(50.),
|
||||
height: mangui::taffy::style::Dimension::Length(100.)
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
fill: Paint::color(Color::rgb(0, 0, 255)),
|
||||
radius: attrs.radius,
|
||||
..Default::default()
|
||||
})),
|
||||
attrs,
|
||||
selfref
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, attrs: Self::PartialComponentAttrs) {
|
||||
let mut to_update = [0; Self::UPDATE_LENGTH];
|
||||
if let Some(radius) = attrs.radius {
|
||||
self.attrs.radius = radius;
|
||||
to_update[0] |= 1;
|
||||
}
|
||||
if to_update.into_iter().reduce(|a,b| a+b).unwrap() != 0 {
|
||||
self.update(&to_update);
|
||||
}
|
||||
}
|
||||
fn get(&self) -> &Self::ComponentAttrs { &self.attrs }
|
||||
|
||||
fn mount(&self, parent: &SharedNode, before: Option<&SharedNode>) {
|
||||
insert(parent, &{self.node.clone()}, before);
|
||||
}
|
||||
|
||||
fn update(&self, bitmap: &[u32]) {
|
||||
self.check_update(bitmap);
|
||||
|
||||
if bitmap[0] & 1 != 0 {
|
||||
self.node.write().unwrap().radius = self.attrs.radius;
|
||||
}
|
||||
|
||||
if bitmap[0] & 1 != 0 {}
|
||||
}
|
||||
|
||||
fn unmount(&self) {
|
||||
detach(&{self.node.clone()});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,33 @@
|
|||
use std::sync::{atomic::AtomicU64, Arc, Mutex, Weak};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::{atomic::AtomicU64, Arc, Mutex, Weak, MutexGuard};
|
||||
|
||||
|
||||
/// Unsubscribes from the store when dropped
|
||||
pub trait StoreUnsubscribe: Drop {}
|
||||
|
||||
pub trait ReadableStore {
|
||||
pub trait Signal {
|
||||
fn subscribe(&self, callback: Box<dyn FnMut()>) -> Box<dyn StoreUnsubscribe>;
|
||||
}
|
||||
|
||||
pub trait ReadableStore: Signal {
|
||||
type State;
|
||||
fn get(&self) -> &Self::State;
|
||||
fn subscribe(&self, callback: Box<dyn FnMut(&Self::State) -> ()>) -> Box<dyn StoreUnsubscribe>;
|
||||
}
|
||||
|
||||
pub trait WritableStore: ReadableStore {
|
||||
fn set(&mut self, state: Self::State);
|
||||
}
|
||||
|
||||
struct Listener<T> {
|
||||
struct Listener {
|
||||
hash: u64,
|
||||
callback: Box<dyn FnMut(&T) -> ()>
|
||||
callback: Box<dyn FnMut()>
|
||||
}
|
||||
|
||||
struct ReadableUnsubscribe<T> {
|
||||
listeners: Weak<Mutex<Vec<Listener<T>>>>,
|
||||
struct ReadableUnsubscribe {
|
||||
listeners: Weak<Mutex<Vec<Listener>>>,
|
||||
hash: u64
|
||||
}
|
||||
|
||||
impl<T: Sized> Drop for ReadableUnsubscribe<T> {
|
||||
impl Drop for ReadableUnsubscribe {
|
||||
fn drop(&mut self) {
|
||||
if let Some(listeners) = self.listeners.upgrade() {
|
||||
let mut listeners = listeners.lock().unwrap();
|
||||
|
|
@ -33,11 +36,11 @@ impl<T: Sized> Drop for ReadableUnsubscribe<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> StoreUnsubscribe for ReadableUnsubscribe<T> {}
|
||||
impl StoreUnsubscribe for ReadableUnsubscribe {}
|
||||
|
||||
pub struct Readable<T> {
|
||||
state: T,
|
||||
listeners: Arc<Mutex<Vec<Listener<T>>>>
|
||||
listeners: Arc<Mutex<Vec<Listener>>>
|
||||
}
|
||||
|
||||
impl<T> Readable<T> {
|
||||
|
|
@ -51,14 +54,11 @@ impl<T> Readable<T> {
|
|||
|
||||
static CALL_COUNT: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
impl<T: 'static> ReadableStore for Readable<T> {
|
||||
type State = T;
|
||||
fn get(&self) -> &Self::State {
|
||||
&self.state
|
||||
}
|
||||
fn subscribe(&self, callback: Box<dyn FnMut(&Self::State) -> ()>) -> Box<dyn StoreUnsubscribe> {
|
||||
impl<T: 'static> Signal for Readable<T> {
|
||||
fn subscribe(&self, mut callback: Box<dyn FnMut()>) -> Box<dyn StoreUnsubscribe> {
|
||||
let hash = CALL_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
let mut listeners = self.listeners.lock().unwrap();
|
||||
callback();
|
||||
listeners.push(Listener {
|
||||
callback,
|
||||
hash
|
||||
|
|
@ -70,9 +70,16 @@ impl<T: 'static> ReadableStore for Readable<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ReadableStore for Readable<T> {
|
||||
type State = T;
|
||||
fn get(&self) -> &Self::State {
|
||||
&self.state
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Writable<T> {
|
||||
state: T,
|
||||
listeners: Arc<Mutex<Vec<Listener<T>>>>
|
||||
listeners: Arc<Mutex<Vec<Listener>>>
|
||||
}
|
||||
|
||||
impl<T> Writable<T> {
|
||||
|
|
@ -84,14 +91,11 @@ impl<T> Writable<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ReadableStore for Writable<T> {
|
||||
type State = T;
|
||||
fn get(&self) -> &Self::State {
|
||||
&self.state
|
||||
}
|
||||
fn subscribe(&self, callback: Box<dyn FnMut(&Self::State) -> ()>) -> Box<dyn StoreUnsubscribe> {
|
||||
impl<T: 'static> Signal for Writable<T> {
|
||||
fn subscribe(&self, mut callback: Box<dyn FnMut()>) -> Box<dyn StoreUnsubscribe> {
|
||||
let hash = CALL_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
let mut listeners = self.listeners.lock().unwrap();
|
||||
callback();
|
||||
listeners.push(Listener {
|
||||
callback,
|
||||
hash
|
||||
|
|
@ -103,12 +107,112 @@ impl<T: 'static> ReadableStore for Writable<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ReadableStore for Writable<T> {
|
||||
type State = T;
|
||||
fn get(&self) -> &Self::State {
|
||||
&self.state
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> WritableStore for Writable<T> {
|
||||
fn set(&mut self, state: Self::State) {
|
||||
self.state = state;
|
||||
let mut listeners = self.listeners.lock().unwrap();
|
||||
for listener in listeners.iter_mut() {
|
||||
(listener.callback)(&self.state);
|
||||
(listener.callback)();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> Default for Writable<T> where T: Default {
|
||||
fn default() -> Self {
|
||||
Self::new(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DerefGuard<T> {
|
||||
listeners: Arc<Mutex<Vec<Listener>>>,
|
||||
tainted: bool,
|
||||
inner: T
|
||||
}
|
||||
|
||||
pub trait DerefGuardExt<T>: WritableStore + Signal {
|
||||
fn guard(&mut self) -> DerefGuard<&mut T>;
|
||||
}
|
||||
|
||||
impl <T: 'static> DerefGuardExt<T> for Writable<T> {
|
||||
fn guard(&mut self) -> DerefGuard<&mut T> {
|
||||
DerefGuard {
|
||||
listeners: self.listeners.clone(),
|
||||
tainted: false,
|
||||
inner: &mut self.state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for DerefGuard<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for DerefGuard<T> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
self.tainted = true;
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for DerefGuard<T> {
|
||||
fn drop(&mut self) {
|
||||
if self.tainted {
|
||||
let mut listeners = self.listeners.lock().unwrap();
|
||||
for listener in listeners.iter_mut() {
|
||||
(listener.callback)();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct VecUnsub {
|
||||
unsubscribes: Vec<Box<dyn StoreUnsubscribe>>
|
||||
}
|
||||
impl Drop for VecUnsub {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
impl StoreUnsubscribe for VecUnsub {}
|
||||
|
||||
|
||||
// odd that I have to implement this but whatever makes the compiler happy
|
||||
impl<T: Signal> Signal for MutexGuard<'_, T> {
|
||||
fn subscribe(&self, callback: Box<dyn FnMut()>) -> Box<dyn StoreUnsubscribe> {
|
||||
self.deref().subscribe(callback)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Signal> Signal for Vec<T> {
|
||||
/// Subscribes to all signals in the vector
|
||||
fn subscribe(&self, callback: Box<dyn FnMut()>) -> Box<dyn StoreUnsubscribe> {
|
||||
let mut unsubscribes = Vec::with_capacity(self.len());
|
||||
let callback = Arc::new(Mutex::new(callback));
|
||||
for signal in self.iter() {
|
||||
let callback = callback.clone();
|
||||
unsubscribes.push(signal.subscribe(Box::new(move || callback.lock().unwrap()())));
|
||||
}
|
||||
Box::new(VecUnsub { unsubscribes })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Signal> Signal for [T] {
|
||||
/// Subscribes to all signals in the array
|
||||
fn subscribe(&self, callback: Box<dyn FnMut()>) -> Box<dyn StoreUnsubscribe> {
|
||||
let mut unsubscribes = Vec::with_capacity(self.len());
|
||||
let callback = Arc::new(Mutex::new(callback));
|
||||
for signal in self.iter() {
|
||||
let callback = callback.clone();
|
||||
unsubscribes.push(signal.subscribe(Box::new(move || callback.lock().unwrap()())));
|
||||
}
|
||||
Box::new(VecUnsub { unsubscribes })
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue