Feat: a few bugs, but the event system works!
This commit is contained in:
1 parent
2041c88d07
commit
3b30fa61b8
13 files changed
+308
-117
No files matched your search
@@ -64,9 +64,9 @@ pub enum Edit<'d> {
|
||||
/// We can go back and forth between the two via methods on GI
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub struct CbIdx {
|
||||
gi_id: usize,
|
||||
gi_gen: u64,
|
||||
listener_idx: usize,
|
||||
pub gi_id: usize,
|
||||
pub gi_gen: u64,
|
||||
pub listener_idx: usize,
|
||||
}
|
||||
|
||||
impl CbIdx {
|
||||
|
||||
@@ -102,6 +102,7 @@ pub mod hooks {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Hook(pub Box<dyn std::any::Any>);
|
||||
|
||||
impl Hook {
|
||||
|
||||
@@ -68,7 +68,7 @@ pub struct DiffMachine<'a> {
|
||||
|
||||
impl<'a> DiffMachine<'a> {
|
||||
pub fn new(bump: &'a Bump) -> Self {
|
||||
log::debug!("starting diff machine");
|
||||
// log::debug!("starting diff machine");
|
||||
Self {
|
||||
change_list: EditMachine::new(bump),
|
||||
immediate_queue: Vec::new(),
|
||||
@@ -88,7 +88,8 @@ impl<'a> DiffMachine<'a> {
|
||||
new: &VNode<'a>,
|
||||
scope: Option<generational_arena::Index>,
|
||||
) {
|
||||
log::debug!("Diffing nodes");
|
||||
log::debug!("old {:#?}", old);
|
||||
log::debug!("new {:#?}", new);
|
||||
|
||||
// Set it while diffing
|
||||
// Reset it when finished diffing
|
||||
@@ -131,7 +132,7 @@ impl<'a> DiffMachine<'a> {
|
||||
// compare elements
|
||||
// if different, schedule different types of update
|
||||
(VNode::Element(eold), VNode::Element(enew)) => {
|
||||
log::debug!("elements are different");
|
||||
// log::debug!("elements are different");
|
||||
// If the element type is completely different, the element needs to be re-rendered completely
|
||||
if enew.tag_name != eold.tag_name || enew.namespace != eold.namespace {
|
||||
self.change_list.commit_traversal();
|
||||
@@ -894,7 +895,7 @@ impl<'a> DiffMachine<'a> {
|
||||
children,
|
||||
namespace,
|
||||
}) => {
|
||||
log::info!("Creating {:#?}", node);
|
||||
// log::info!("Creating {:#?}", node);
|
||||
if let Some(namespace) = namespace {
|
||||
self.change_list.create_element_ns(tag_name, namespace);
|
||||
} else {
|
||||
|
||||
@@ -6,16 +6,29 @@
|
||||
//! The goal here is to provide a consistent event interface across all renderer types
|
||||
use generational_arena::Index;
|
||||
|
||||
use crate::innerlude::CbIdx;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EventTrigger {
|
||||
pub component_id: Index,
|
||||
pub listener_id: u32,
|
||||
pub listener_id: usize,
|
||||
pub event: VirtualEvent,
|
||||
}
|
||||
|
||||
impl EventTrigger {
|
||||
pub fn new() -> Self {
|
||||
todo!()
|
||||
pub fn new(event: VirtualEvent, cb: CbIdx) -> Self {
|
||||
let CbIdx {
|
||||
gi_id,
|
||||
gi_gen,
|
||||
listener_idx,
|
||||
} = cb;
|
||||
|
||||
let component_id = Index::from_raw_parts(gi_id, gi_gen);
|
||||
Self {
|
||||
component_id,
|
||||
listener_id: listener_idx,
|
||||
event,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ mod use_state_def {
|
||||
caller: Box::new(|_| println!("setter called!")),
|
||||
},
|
||||
move |hook| {
|
||||
log::debug!("Use_state set called");
|
||||
let inner = hook.new_val.clone();
|
||||
let scheduled_update = ctx.schedule_update();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::{
|
||||
events::VirtualEvent,
|
||||
innerlude::VComponent,
|
||||
nodes::{Attribute, Listener, NodeKey, VNode},
|
||||
prelude::VElement,
|
||||
@@ -338,7 +339,7 @@ where
|
||||
/// .finish();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn on(mut self, event: &'static str, callback: impl Fn(()) + 'a) -> Self {
|
||||
pub fn on(mut self, event: &'static str, callback: impl Fn(VirtualEvent) + 'a) -> Self {
|
||||
self.listeners.push(Listener {
|
||||
event,
|
||||
callback: self.bump.alloc(callback),
|
||||
@@ -1081,7 +1082,7 @@ pub fn on<'a, 'b>(
|
||||
// pub fn on<'a, 'b, F: 'static>(
|
||||
bump: &'a Bump,
|
||||
event: &'static str,
|
||||
callback: impl Fn(()) + 'a,
|
||||
callback: impl Fn(VirtualEvent) + 'a,
|
||||
) -> Listener<'a> {
|
||||
Listener {
|
||||
event,
|
||||
|
||||
@@ -94,6 +94,8 @@ mod vnode {
|
||||
}
|
||||
|
||||
mod velement {
|
||||
use crate::events::VirtualEvent;
|
||||
|
||||
use super::*;
|
||||
use std::fmt::Debug;
|
||||
|
||||
@@ -188,7 +190,7 @@ mod velement {
|
||||
// pub(crate) _i: &'bump str,
|
||||
// #[serde(skip_serializing, skip_deserializing, default="")]
|
||||
// /// The callback to invoke when the event happens.
|
||||
pub(crate) callback: &'bump (dyn Fn(())),
|
||||
pub(crate) callback: &'bump (dyn Fn(VirtualEvent)),
|
||||
}
|
||||
impl Debug for Listener<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
@@ -197,7 +199,7 @@ mod velement {
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
pub(crate) type ListenerCallback<'a> = &'a (dyn Fn(()));
|
||||
pub(crate) type ListenerCallback<'a> = &'a (dyn Fn(VirtualEvent));
|
||||
union CallbackFatPtr<'a> {
|
||||
callback: ListenerCallback<'a>,
|
||||
parts: (u32, u32),
|
||||
|
||||
+50
-11
@@ -36,8 +36,10 @@ pub struct Scope {
|
||||
|
||||
pub frames: ActiveFrame,
|
||||
|
||||
// IE Which listeners need to be woken up?
|
||||
pub listeners: Vec<Box<dyn Fn(crate::events::VirtualEvent)>>,
|
||||
// List of listeners generated when CTX is evaluated
|
||||
pub listeners: Vec<*const dyn Fn(crate::events::VirtualEvent)>,
|
||||
// pub listeners: Vec<*const dyn Fn(crate::events::VirtualEvent)>,
|
||||
// pub listeners: Vec<Box<dyn Fn(crate::events::VirtualEvent)>>,
|
||||
|
||||
// lying, cheating reference >:(
|
||||
pub props: Box<dyn std::any::Any>,
|
||||
@@ -55,9 +57,8 @@ impl Scope {
|
||||
// Capture the caller
|
||||
let caller = f as *const ();
|
||||
|
||||
let listeners: Vec<Box<dyn Fn(crate::events::VirtualEvent)>> = vec![Box::new(|_| {
|
||||
log::info!("Base listener called");
|
||||
})];
|
||||
let listeners = vec![];
|
||||
// let listeners: Vec<Box<dyn Fn(crate::events::VirtualEvent)>> = vec![];
|
||||
|
||||
let old_frame = BumpFrame {
|
||||
bump: Bump::new(),
|
||||
@@ -95,6 +96,7 @@ impl Scope {
|
||||
let frame = {
|
||||
let frame = self.frames.next();
|
||||
frame.bump.reset();
|
||||
log::debug!("Rednering into frame {:?}", frame as *const _);
|
||||
frame
|
||||
};
|
||||
|
||||
@@ -145,6 +147,20 @@ impl Scope {
|
||||
.borrow_mut()
|
||||
.take()
|
||||
.expect("Viewing did not happen");
|
||||
|
||||
// todo:
|
||||
// make this so we dont have to iterate through the vnodes to get its listener
|
||||
let mut listeners = vec![];
|
||||
retrieve_listeners(&frame.head_node, &mut listeners);
|
||||
self.listeners = listeners
|
||||
.into_iter()
|
||||
.map(|f| {
|
||||
let g = f.callback;
|
||||
g as *const _
|
||||
})
|
||||
.collect();
|
||||
|
||||
// consume the listeners from the head_node into a list of boxed ref listeners
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,6 +175,18 @@ impl Scope {
|
||||
}
|
||||
}
|
||||
|
||||
fn retrieve_listeners(node: &VNode<'static>, listeners: &mut Vec<&Listener>) {
|
||||
if let VNode::Element(el) = *node {
|
||||
for listener in el.listeners {
|
||||
// let g = listener as *const Listener;
|
||||
listeners.push(listener);
|
||||
}
|
||||
for child in el.children {
|
||||
retrieve_listeners(child, listeners);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// todo, do better with the active frame stuff
|
||||
// somehow build this vnode with a lifetime tied to self
|
||||
// This root node has "static" lifetime, but it's really not static.
|
||||
@@ -184,7 +212,7 @@ impl ActiveFrame {
|
||||
}
|
||||
|
||||
fn current_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
||||
let raw_node = match self.idx.borrow().load(Ordering::Relaxed) & 1 != 0 {
|
||||
let raw_node = match self.idx.borrow().load(Ordering::Relaxed) & 1 == 0 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
};
|
||||
@@ -196,7 +224,7 @@ impl ActiveFrame {
|
||||
}
|
||||
|
||||
fn prev_head_node<'b>(&'b self) -> &'b VNode<'b> {
|
||||
let raw_node = match self.idx.borrow().load(Ordering::Relaxed) & 1 == 0 {
|
||||
let raw_node = match self.idx.borrow().load(Ordering::Relaxed) & 1 != 0 {
|
||||
true => &self.frames[0],
|
||||
false => &self.frames[1],
|
||||
};
|
||||
@@ -211,11 +239,22 @@ impl ActiveFrame {
|
||||
fn next(&mut self) -> &mut BumpFrame {
|
||||
self.idx.fetch_add(1, Ordering::Relaxed);
|
||||
let cur = self.idx.borrow().load(Ordering::Relaxed);
|
||||
match cur % 1 {
|
||||
1 => &mut self.frames[1],
|
||||
0 => &mut self.frames[0],
|
||||
_ => unreachable!("mod cannot by non-zero"),
|
||||
log::debug!("Next frame! {}", cur);
|
||||
|
||||
if cur % 2 == 0 {
|
||||
log::debug!("Chosing frame 0");
|
||||
&mut self.frames[0]
|
||||
} else {
|
||||
log::debug!("Chosing frame 1");
|
||||
&mut self.frames[1]
|
||||
}
|
||||
// match cur % 1 {
|
||||
// 0 => {
|
||||
// }
|
||||
// 1 => {
|
||||
// }
|
||||
// _ => unreachable!("mod cannot by non-zero"),
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,29 +140,63 @@ impl VirtualDom {
|
||||
|
||||
let component = self
|
||||
.components
|
||||
.get(component_id)
|
||||
.get_mut(component_id)
|
||||
.expect("Component should exist if an event was triggered");
|
||||
|
||||
let listener = component
|
||||
.listeners
|
||||
.get(listener_id as usize)
|
||||
.expect("Listener should exist if it was triggered")
|
||||
.as_ref();
|
||||
log::debug!("list: {}", component.listeners.len());
|
||||
|
||||
let listener = unsafe {
|
||||
component
|
||||
.listeners
|
||||
.get(listener_id as usize)
|
||||
.expect("Listener should exist if it was triggered")
|
||||
.as_ref()
|
||||
}
|
||||
.unwrap();
|
||||
|
||||
// Run the callback with the user event
|
||||
listener(source);
|
||||
|
||||
// Reset and then build a new diff machine
|
||||
// The previous edit list cannot be around while &mut is held
|
||||
// Make sure variance doesnt break this
|
||||
self.diff_bump.reset();
|
||||
let mut diff_machine = DiffMachine::new(&self.diff_bump);
|
||||
|
||||
// this is still a WIP
|
||||
// we'll need to re-fecth all the scopes that were changed and build the diff machine
|
||||
// fetch the component again
|
||||
// let component = self
|
||||
// .components
|
||||
// .get_mut(self.base_scope)
|
||||
// .expect("Root should always exist");
|
||||
|
||||
component.run::<()>();
|
||||
|
||||
diff_machine.diff_node(
|
||||
component.old_frame(),
|
||||
component.new_frame(),
|
||||
Some(self.base_scope),
|
||||
);
|
||||
// diff_machine.diff_node(
|
||||
// component.old_frame(),
|
||||
// component.new_frame(),
|
||||
// Some(self.base_scope),
|
||||
// );
|
||||
|
||||
Ok(diff_machine.consume())
|
||||
// Err(crate::error::Error::NoEvent)
|
||||
// Mark dirty components. Descend from the highest node until all dirty nodes are updated.
|
||||
let mut affected_components = Vec::new();
|
||||
// let mut affected_components = Vec::new();
|
||||
|
||||
while let Some(event) = self.pop_event() {
|
||||
if let Some(component_idx) = event.index() {
|
||||
affected_components.push(component_idx);
|
||||
}
|
||||
self.process_lifecycle(event)?;
|
||||
}
|
||||
// while let Some(event) = self.pop_event() {
|
||||
// if let Some(component_idx) = event.index() {
|
||||
// affected_components.push(component_idx);
|
||||
// }
|
||||
// self.process_lifecycle(event)?;
|
||||
// }
|
||||
|
||||
todo!()
|
||||
// todo!()
|
||||
}
|
||||
|
||||
/// Using mutable access to the Virtual Dom, progress a given lifecycle event
|
||||
|
||||
Reference in new issue
Block a user