feat: get desktop working with just creation
This commit is contained in:
1 parent
8caabb97d8
commit
e8ae830cf2
16 files changed
+1301
-329
No files matched your search
@@ -47,6 +47,7 @@ impl VirtualDom {
|
||||
// todo: adjust dynamic nodes to be in the order of roots and then leaves (ie BFS)
|
||||
let mut dynamic_attrs = template.template.attr_paths.iter().enumerate().peekable();
|
||||
let mut dynamic_nodes = template.template.node_paths.iter().enumerate().peekable();
|
||||
let cur_scope = self.scope_stack.last().copied().unwrap();
|
||||
|
||||
let mut on_stack = 0;
|
||||
for (root_idx, root) in template.template.roots.iter().enumerate() {
|
||||
@@ -78,21 +79,25 @@ impl VirtualDom {
|
||||
});
|
||||
|
||||
loop {
|
||||
let attribute = &template.dynamic_attrs[attr_id];
|
||||
let attribute = template.dynamic_attrs.get(attr_id).unwrap();
|
||||
attribute.mounted_element.set(id);
|
||||
|
||||
match attribute.value {
|
||||
match &attribute.value {
|
||||
AttributeValue::Text(value) => mutations.push(SetAttribute {
|
||||
name: attribute.name,
|
||||
value,
|
||||
value: *value,
|
||||
id,
|
||||
}),
|
||||
AttributeValue::Bool(value) => mutations.push(SetBoolAttribute {
|
||||
name: attribute.name,
|
||||
value,
|
||||
value: *value,
|
||||
id,
|
||||
}),
|
||||
AttributeValue::Listener(_) => mutations.push(NewEventListener {
|
||||
event_name: attribute.name,
|
||||
scope: cur_scope,
|
||||
id,
|
||||
}),
|
||||
AttributeValue::Listener(_) => todo!("create listener attributes"),
|
||||
AttributeValue::Float(_) => todo!(),
|
||||
AttributeValue::Int(_) => todo!(),
|
||||
AttributeValue::Any(_) => todo!(),
|
||||
@@ -138,8 +143,8 @@ impl VirtualDom {
|
||||
let id = self.next_element(template);
|
||||
mutations.push(CreatePlaceholder { id })
|
||||
}
|
||||
TemplateNode::Text(value) => mutations.push(CreateText { value }),
|
||||
TemplateNode::DynamicText { .. } => mutations.push(CreateText {
|
||||
TemplateNode::Text(value) => mutations.push(CreateTextNode { value }),
|
||||
TemplateNode::DynamicText { .. } => mutations.push(CreateTextNode {
|
||||
value: "placeholder",
|
||||
}),
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ impl<'b> VirtualDom {
|
||||
|
||||
(DynamicNode::Text { id: lid, .. }, right) => {
|
||||
let m = self.create_dynamic_node(muts, right_template, right, idx);
|
||||
muts.push(Mutation::Replace { id: lid.get(), m });
|
||||
muts.push(Mutation::ReplaceWith { id: lid.get(), m });
|
||||
}
|
||||
|
||||
(DynamicNode::Placeholder(_), DynamicNode::Placeholder(_)) => todo!(),
|
||||
|
||||
@@ -6,11 +6,18 @@ use std::{
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
pub struct UiEvent<T> {
|
||||
bubble_state: Cell<bool>,
|
||||
data: Rc<T>,
|
||||
pub struct UiEvent<T: 'static> {
|
||||
pub(crate) bubble_state: Cell<bool>,
|
||||
pub(crate) data: Rc<T>,
|
||||
}
|
||||
impl<T> Clone for UiEvent<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
bubble_state: self.bubble_state.clone(),
|
||||
data: self.data.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UiEvent<T> {
|
||||
pub fn cancel_bubble(&self) {
|
||||
self.bubble_state.set(false);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::arena::ElementId;
|
||||
use crate::{arena::ElementId, ScopeId};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Mutations<'a> {
|
||||
@@ -35,9 +35,61 @@ impl std::ops::DerefMut for Mutations<'_> {
|
||||
each subtree has its own numbering scheme
|
||||
*/
|
||||
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(
|
||||
feature = "serialize",
|
||||
derive(serde::Serialize, serde::Deserialize),
|
||||
serde(tag = "type")
|
||||
)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Mutation<'a> {
|
||||
AppendChildren {
|
||||
m: usize,
|
||||
},
|
||||
|
||||
AssignId {
|
||||
path: &'static [u8],
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
CreateElement {
|
||||
name: &'a str,
|
||||
namespace: Option<&'a str>,
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
CreatePlaceholder {
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
CreateTextNode {
|
||||
value: &'a str,
|
||||
},
|
||||
HydrateText {
|
||||
path: &'static [u8],
|
||||
value: &'a str,
|
||||
id: ElementId,
|
||||
},
|
||||
LoadTemplate {
|
||||
name: &'static str,
|
||||
index: usize,
|
||||
},
|
||||
|
||||
// Take the current element and replace it with the element with the given id.
|
||||
ReplaceWith {
|
||||
id: ElementId,
|
||||
m: usize,
|
||||
},
|
||||
|
||||
ReplacePlaceholder {
|
||||
m: usize,
|
||||
path: &'static [u8],
|
||||
},
|
||||
|
||||
SaveTemplate {
|
||||
name: &'static str,
|
||||
m: usize,
|
||||
},
|
||||
|
||||
SetAttribute {
|
||||
name: &'a str,
|
||||
value: &'a str,
|
||||
@@ -50,20 +102,8 @@ pub enum Mutation<'a> {
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
LoadTemplate {
|
||||
name: &'static str,
|
||||
index: usize,
|
||||
},
|
||||
|
||||
SaveTemplate {
|
||||
name: &'static str,
|
||||
m: usize,
|
||||
},
|
||||
|
||||
HydrateText {
|
||||
path: &'static [u8],
|
||||
SetInnerText {
|
||||
value: &'a str,
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
SetText {
|
||||
@@ -71,41 +111,24 @@ pub enum Mutation<'a> {
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
ReplacePlaceholder {
|
||||
m: usize,
|
||||
path: &'static [u8],
|
||||
},
|
||||
/// Create a new Event Listener.
|
||||
NewEventListener {
|
||||
/// The name of the event to listen for.
|
||||
event_name: &'a str,
|
||||
|
||||
AssignId {
|
||||
path: &'static [u8],
|
||||
/// The ID of the node to attach the listener to.
|
||||
scope: ScopeId,
|
||||
|
||||
/// The ID of the node to attach the listener to.
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
// Take the current element and replace it with the element with the given id.
|
||||
Replace {
|
||||
/// Remove an existing Event Listener.
|
||||
RemoveEventListener {
|
||||
/// The ID of the node to remove.
|
||||
id: ElementId,
|
||||
m: usize,
|
||||
},
|
||||
|
||||
CreateElement {
|
||||
name: &'a str,
|
||||
namespace: Option<&'a str>,
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
SetInnerText {
|
||||
value: &'a str,
|
||||
},
|
||||
|
||||
CreateText {
|
||||
value: &'a str,
|
||||
},
|
||||
|
||||
CreatePlaceholder {
|
||||
id: ElementId,
|
||||
},
|
||||
|
||||
AppendChildren {
|
||||
m: usize,
|
||||
/// The name of the event to remove.
|
||||
event: &'a str,
|
||||
},
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::{any_props::AnyProps, arena::ElementId, ScopeId, ScopeState};
|
||||
use crate::{any_props::AnyProps, arena::ElementId, ScopeId, ScopeState, UiEvent};
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
cell::{Cell, RefCell},
|
||||
hash::Hasher,
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
pub type TemplateId = &'static str;
|
||||
@@ -154,6 +155,27 @@ pub enum AttributeValue<'a> {
|
||||
None,
|
||||
}
|
||||
|
||||
impl<'a> AttributeValue<'a> {
|
||||
pub fn new_listener<T: 'static>(
|
||||
cx: &'a ScopeState,
|
||||
mut f: impl FnMut(UiEvent<T>) + 'a,
|
||||
) -> AttributeValue<'a> {
|
||||
let f = cx.bump().alloc(move |a: &dyn Any| {
|
||||
a.downcast_ref::<UiEvent<T>>()
|
||||
.map(|a| f(a.clone()))
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"Expected UiEvent<{}>, got {:?}",
|
||||
std::any::type_name::<T>(),
|
||||
a
|
||||
)
|
||||
})
|
||||
}) as &mut dyn FnMut(&dyn Any);
|
||||
|
||||
AttributeValue::Listener(RefCell::new(f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Debug for AttributeValue<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::{
|
||||
nodes::{Template, TemplateId},
|
||||
scheduler::{SuspenseBoundary, SuspenseId},
|
||||
scopes::{ScopeId, ScopeState},
|
||||
Attribute, AttributeValue, Element, EventPriority, Scope, SuspenseContext,
|
||||
Attribute, AttributeValue, Element, EventPriority, Scope, SuspenseContext, UiEvent,
|
||||
};
|
||||
use futures_util::{pin_mut, FutureExt, StreamExt};
|
||||
use slab::Slab;
|
||||
@@ -288,10 +288,10 @@ impl VirtualDom {
|
||||
///
|
||||
///
|
||||
///
|
||||
pub fn handle_event(
|
||||
pub fn handle_event<T: 'static>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
event: &dyn Any,
|
||||
data: Rc<T>,
|
||||
element: ElementId,
|
||||
bubbles: bool,
|
||||
priority: EventPriority,
|
||||
@@ -304,6 +304,11 @@ impl VirtualDom {
|
||||
- send event to virtualdom
|
||||
*/
|
||||
|
||||
let event = UiEvent {
|
||||
bubble_state: std::cell::Cell::new(true),
|
||||
data,
|
||||
};
|
||||
|
||||
let path = &self.elements[element.0];
|
||||
let template = unsafe { &*path.template };
|
||||
let dynamic = &template.dynamic_nodes[path.element];
|
||||
@@ -339,7 +344,7 @@ impl VirtualDom {
|
||||
|
||||
for listener in listeners {
|
||||
if let AttributeValue::Listener(listener) = &listener.value {
|
||||
(listener.borrow_mut())(event)
|
||||
(listener.borrow_mut())(&event.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user