update tui with new mutations

This commit is contained in:
Evan Almloff committed 2022-12-04 20:39:54 -06:00
1 parent f21d099ae4
commit 8c07b4059f
13 files changed
+335 -330

No files matched your search

+1 -1
View File
@@ -493,7 +493,7 @@ impl<'a> StateMember<'a> {
let mask = self let mask = self
.dep_mems .dep_mems
.iter() .iter()
.map(|m| 1 << m.id) .map(|m| 1u64 << m.id)
.fold(1 << self.mem.id, |a, b| a | b); .fold(1 << self.mem.id, |a, b| a | b);
quote! { quote! {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
+1 -1
View File
@@ -15,7 +15,7 @@ dioxus-core = { path = "../core", version = "^0.2.1" }
dioxus-html = { path = "../html", version = "^0.2.1" } dioxus-html = { path = "../html", version = "^0.2.1" }
dioxus-core-macro = { path = "../core-macro", version = "^0.2.1" } dioxus-core-macro = { path = "../core-macro", version = "^0.2.1" }
taffy = "0.2.0" taffy = "0.2.1"
smallvec = "1.6" smallvec = "1.6"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
anymap = "0.12.1" anymap = "0.12.1"
+2 -2
View File
@@ -18,8 +18,8 @@ pub mod utils;
/// A id for a node that lives in the real dom. /// A id for a node that lives in the real dom.
pub type RealNodeId = NodeId; pub type RealNodeId = NodeId;
pub(crate) type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>; pub type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
pub(crate) type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>; pub type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>;
pub type SendAnyMap = anymap::Map<dyn anymap::any::Any + Send + Sync + 'static>; pub type SendAnyMap = anymap::Map<dyn anymap::any::Any + Send + Sync + 'static>;
/// Used in derived state macros /// Used in derived state macros
+159 -163
View File
@@ -151,184 +151,180 @@ impl<S: State> RealDom<S> {
} }
/// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state. /// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
pub fn apply_mutations(&mut self, mutations_vec: Vec<Mutations>) -> DirtyNodeStates { pub fn apply_mutations(&mut self, mutations: Mutations) -> DirtyNodeStates {
let mut nodes_updated: FxHashMap<RealNodeId, NodeMask> = FxHashMap::default(); let mut nodes_updated: FxHashMap<RealNodeId, NodeMask> = FxHashMap::default();
for mutations in mutations_vec { for template in mutations.templates {
for template in mutations.templates { let mut template_root_ids = Vec::new();
let mut template_root_ids = Vec::new(); for root in template.roots {
for root in template.roots { if let Some(id) = self.create_template_node(root, &mut nodes_updated) {
if let Some(id) = self.create_template_node(root, &mut nodes_updated) { template_root_ids.push(id);
template_root_ids.push(id); }
}
self.templates
.insert(template.name.to_string(), template_root_ids);
}
for e in mutations.edits {
use dioxus_core::Mutation::*;
match e {
AppendChildren { id, m } => {
let children = self.stack.split_off(m);
let parent = self.element_to_node_id(id);
for child in children {
self.add_child(parent, child);
mark_dirty(parent, NodeMask::ALL, &mut nodes_updated);
} }
} }
self.templates AssignId { path, id } => {
.insert(template.name.to_string(), template_root_ids); self.set_element_id(self.load_child(path), id);
} }
for e in mutations.edits { CreatePlaceholder { id } => {
use dioxus_core::Mutation::*; let node = Node::new(NodeType::Placeholder);
match e { let node_id = self.create_node(node);
AppendChildren { id, m } => { self.set_element_id(node_id, id);
let children = self.stack.split_off(m); self.stack.push(node_id);
let parent = self.element_to_node_id(id); mark_dirty(node_id, NodeMask::ALL, &mut nodes_updated);
for child in children { }
self.add_child(parent, child); CreateTextNode { value, id } => {
mark_dirty(parent, NodeMask::ALL, &mut nodes_updated); let node = Node::new(NodeType::Text {
} text: value.to_string(),
});
let node_id = self.create_node(node);
let node = self.tree.get_mut(node_id).unwrap();
node.node_data.element_id = Some(id);
self.stack.push(node_id);
mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
}
HydrateText { path, value, id } => {
let node_id = self.load_child(path);
self.set_element_id(node_id, id);
let node = self.tree.get_mut(node_id).unwrap();
if let NodeType::Text { text } = &mut node.node_data.node_type {
*text = value.to_string();
} }
AssignId { path, id } => { mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
self.set_element_id(self.load_child(path), id); }
LoadTemplate { name, index, id } => {
let template_id = self.templates[name][index];
let clone_id = self.clone_node(template_id, &mut nodes_updated);
self.set_element_id(clone_id, id);
}
ReplaceWith { id, m } => {
let new_nodes = self.stack.split_off(m);
let old_node_id = self.element_to_node_id(id);
for new in new_nodes {
self.tree.insert_after(old_node_id, new);
mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
} }
CreatePlaceholder { id } => { self.tree.remove(old_node_id);
let node = Node::new(NodeType::Placeholder); }
let node_id = self.create_node(node); ReplacePlaceholder { path, m } => {
self.set_element_id(node_id, id); let new_nodes = self.stack.split_off(m);
self.stack.push(node_id); let old_node_id = self.load_child(path);
mark_dirty(node_id, NodeMask::ALL, &mut nodes_updated); for new in new_nodes {
self.tree.insert_after(old_node_id, new);
mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
} }
CreateTextNode { value, id } => { self.tree.remove(old_node_id);
let node = Node::new(NodeType::Text { }
text: value.to_string(), InsertAfter { id, m } => {
}); let new_nodes = self.stack.split_off(m);
let node_id = self.create_node(node); let old_node_id = self.element_to_node_id(id);
let node = self.tree.get_mut(node_id).unwrap(); for new in new_nodes {
node.node_data.element_id = Some(id); self.tree.insert_after(old_node_id, new);
self.stack.push(node_id); mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
} }
HydrateText { path, value, id } => { }
let node_id = self.load_child(path); InsertBefore { id, m } => {
self.set_element_id(node_id, id); let new_nodes = self.stack.split_off(m);
let node = self.tree.get_mut(node_id).unwrap(); let old_node_id = self.element_to_node_id(id);
if let NodeType::Text { text } = &mut node.node_data.node_type { for new in new_nodes {
*text = value.to_string(); self.tree.insert_before(old_node_id, new);
} mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
} }
LoadTemplate { name, index, id } => { }
let template_id = self.templates[name][index]; SetAttribute {
let clone_id = self.clone_node(template_id, &mut nodes_updated); name,
self.set_element_id(clone_id, id); value,
id,
ns,
} => {
let node_id = self.element_to_node_id(id);
let node = self.tree.get_mut(node_id).unwrap();
if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type {
attributes.insert(
OwnedAttributeDiscription {
name: name.to_string(),
namespace: ns.map(|s| s.to_string()),
volatile: false,
},
crate::node::OwnedAttributeValue::Text(value.to_string()),
);
mark_dirty(
node_id,
NodeMask::new_with_attrs(AttributeMask::single(name)),
&mut nodes_updated,
);
} }
ReplaceWith { id, m } => { }
let new_nodes = self.stack.split_off(m); SetBoolAttribute { name, value, id } => {
let old_node_id = self.element_to_node_id(id); let node_id = self.element_to_node_id(id);
for new in new_nodes { let node = self.tree.get_mut(node_id).unwrap();
self.tree.insert_after(old_node_id, new); if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type {
mark_dirty(new, NodeMask::ALL, &mut nodes_updated); attributes.insert(
} OwnedAttributeDiscription {
self.tree.remove(old_node_id); name: name.to_string(),
namespace: None,
volatile: false,
},
crate::node::OwnedAttributeValue::Bool(value),
);
mark_dirty(
node_id,
NodeMask::new_with_attrs(AttributeMask::single(name)),
&mut nodes_updated,
);
} }
ReplacePlaceholder { path, m } => { }
let new_nodes = self.stack.split_off(m); SetText { value, id } => {
let old_node_id = self.load_child(path); let node_id = self.element_to_node_id(id);
for new in new_nodes { let node = self.tree.get_mut(node_id).unwrap();
self.tree.insert_after(old_node_id, new); if let NodeType::Text { text } = &mut node.node_data.node_type {
mark_dirty(new, NodeMask::ALL, &mut nodes_updated); *text = value.to_string();
}
self.tree.remove(old_node_id);
} }
InsertAfter { id, m } => { mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
let new_nodes = self.stack.split_off(m); }
let old_node_id = self.element_to_node_id(id); NewEventListener { name, scope: _, id } => {
for new in new_nodes { let node_id = self.element_to_node_id(id);
self.tree.insert_after(old_node_id, new); let node = self.tree.get_mut(node_id).unwrap();
mark_dirty(new, NodeMask::ALL, &mut nodes_updated); if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
} match self.nodes_listening.get_mut(name) {
} Some(hs) => {
InsertBefore { id, m } => { hs.insert(node_id);
let new_nodes = self.stack.split_off(m); }
let old_node_id = self.element_to_node_id(id); None => {
for new in new_nodes { let mut hs = FxHashSet::default();
self.tree.insert_before(old_node_id, new); hs.insert(node_id);
mark_dirty(new, NodeMask::ALL, &mut nodes_updated); self.nodes_listening.insert(name.to_string(), hs);
}
}
SetAttribute {
name,
value,
id,
ns,
} => {
let node_id = self.element_to_node_id(id);
let node = self.tree.get_mut(node_id).unwrap();
if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type
{
attributes.insert(
OwnedAttributeDiscription {
name: name.to_string(),
namespace: ns.map(|s| s.to_string()),
volatile: false,
},
crate::node::OwnedAttributeValue::Text(value.to_string()),
);
mark_dirty(
node_id,
NodeMask::new_with_attrs(AttributeMask::single(name)),
&mut nodes_updated,
);
}
}
SetBoolAttribute { name, value, id } => {
let node_id = self.element_to_node_id(id);
let node = self.tree.get_mut(node_id).unwrap();
if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type
{
attributes.insert(
OwnedAttributeDiscription {
name: name.to_string(),
namespace: None,
volatile: false,
},
crate::node::OwnedAttributeValue::Bool(value),
);
mark_dirty(
node_id,
NodeMask::new_with_attrs(AttributeMask::single(name)),
&mut nodes_updated,
);
}
}
SetText { value, id } => {
let node_id = self.element_to_node_id(id);
let node = self.tree.get_mut(node_id).unwrap();
if let NodeType::Text { text } = &mut node.node_data.node_type {
*text = value.to_string();
}
mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
}
NewEventListener { name, scope: _, id } => {
let node_id = self.element_to_node_id(id);
let node = self.tree.get_mut(node_id).unwrap();
if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
match self.nodes_listening.get_mut(name) {
Some(hs) => {
hs.insert(node_id);
}
None => {
let mut hs = FxHashSet::default();
hs.insert(node_id);
self.nodes_listening.insert(name.to_string(), hs);
}
} }
listeners.insert(name.to_string());
} }
listeners.insert(name.to_string());
} }
RemoveEventListener { id, name } => { }
let node_id = self.element_to_node_id(id); RemoveEventListener { id, name } => {
let node = self.tree.get_mut(node_id).unwrap(); let node_id = self.element_to_node_id(id);
if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type { let node = self.tree.get_mut(node_id).unwrap();
listeners.remove(name); if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
} listeners.remove(name);
self.nodes_listening.get_mut(name).unwrap().remove(&node_id);
}
Remove { id } => {
let node_id = self.element_to_node_id(id);
self.tree.remove(node_id);
}
PushRoot { id } => {
let node_id = self.element_to_node_id(id);
self.stack.push(node_id);
} }
self.nodes_listening.get_mut(name).unwrap().remove(&node_id);
}
Remove { id } => {
let node_id = self.element_to_node_id(id);
self.tree.remove(node_id);
}
PushRoot { id } => {
let node_id = self.element_to_node_id(id);
self.stack.push(node_id);
} }
} }
} }
+2 -1
View File
@@ -23,10 +23,11 @@ crossterm = "0.23.0"
anyhow = "1.0.42" anyhow = "1.0.42"
tokio = { version = "1.15.0", features = ["full"] } tokio = { version = "1.15.0", features = ["full"] }
futures = "0.3.19" futures = "0.3.19"
taffy = "0.1.0" taffy = "0.2.1"
smallvec = "1.6" smallvec = "1.6"
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
anymap = "0.12.1" anymap = "0.12.1"
futures-channel = "0.3.25"
[dev-dependencies] [dev-dependencies]
dioxus = { path = "../dioxus" } dioxus = { path = "../dioxus" }
+15 -14
View File
@@ -1,6 +1,7 @@
use crate::{node::PreventDefault, Dom}; use crate::{node::PreventDefault, TuiDom};
use dioxus_native_core::{ use dioxus_native_core::{
tree::TreeView,
utils::{ElementProduced, PersistantElementIter}, utils::{ElementProduced, PersistantElementIter},
RealNodeId, RealNodeId,
}; };
@@ -10,7 +11,6 @@ use std::{cmp::Ordering, num::NonZeroU16};
use dioxus_native_core::{ use dioxus_native_core::{
node_ref::{AttributeMask, NodeMask, NodeView}, node_ref::{AttributeMask, NodeMask, NodeView},
real_dom::NodeType,
state::NodeDepState, state::NodeDepState,
}; };
@@ -64,7 +64,8 @@ pub(crate) struct Focus {
pub level: FocusLevel, pub level: FocusLevel,
} }
impl NodeDepState<()> for Focus { impl NodeDepState for Focus {
type DepState = ();
type Ctx = (); type Ctx = ();
const NODE_MASK: NodeMask = const NODE_MASK: NodeMask =
NodeMask::new_with_attrs(AttributeMask::Static(FOCUS_ATTRIBUTES)).with_listeners(); NodeMask::new_with_attrs(AttributeMask::Static(FOCUS_ATTRIBUTES)).with_listeners();
@@ -77,7 +78,7 @@ impl NodeDepState<()> for Focus {
{ {
if let Some(index) = a if let Some(index) = a
.value .value
.as_int32() .as_int()
.or_else(|| a.value.as_text().and_then(|v| v.parse::<i32>().ok())) .or_else(|| a.value.as_text().and_then(|v| v.parse::<i32>().ok()))
{ {
match index.cmp(&0) { match index.cmp(&0) {
@@ -126,7 +127,7 @@ pub(crate) struct FocusState {
impl FocusState { impl FocusState {
/// Returns true if the focus has changed. /// Returns true if the focus has changed.
pub fn progress(&mut self, rdom: &mut Dom, forward: bool) -> bool { pub fn progress(&mut self, rdom: &mut TuiDom, forward: bool) -> bool {
if let Some(last) = self.last_focused_id { if let Some(last) = self.last_focused_id {
if rdom[last].state.prevent_default == PreventDefault::KeyDown { if rdom[last].state.prevent_default == PreventDefault::KeyDown {
return false; return false;
@@ -234,10 +235,10 @@ impl FocusState {
false false
} }
pub(crate) fn prune(&mut self, mutations: &dioxus_core::Mutations, rdom: &Dom) { pub(crate) fn prune(&mut self, mutations: &dioxus_core::Mutations, rdom: &TuiDom) {
fn remove_children( fn remove_children(
to_prune: &mut [&mut Option<RealNodeId>], to_prune: &mut [&mut Option<RealNodeId>],
rdom: &Dom, rdom: &TuiDom,
removed: RealNodeId, removed: RealNodeId,
) { ) {
for opt in to_prune.iter_mut() { for opt in to_prune.iter_mut() {
@@ -247,8 +248,8 @@ impl FocusState {
} }
} }
} }
if let NodeType::Element { children, .. } = &rdom[removed].node_data.node_type { if let Some(children) = &rdom.children_ids(removed) {
for child in children { for child in *children {
remove_children(to_prune, rdom, *child); remove_children(to_prune, rdom, *child);
} }
} }
@@ -258,22 +259,22 @@ impl FocusState {
} }
for m in &mutations.edits { for m in &mutations.edits {
match m { match m {
dioxus_core::DomEdit::ReplaceWith { root, .. } => remove_children( dioxus_core::Mutation::ReplaceWith { id, .. } => remove_children(
&mut [&mut self.last_focused_id], &mut [&mut self.last_focused_id],
rdom, rdom,
rdom.resolve_maybe_id(*root), rdom.element_to_node_id(*id),
), ),
dioxus_core::DomEdit::Remove { root } => remove_children( dioxus_core::Mutation::Remove { id } => remove_children(
&mut [&mut self.last_focused_id], &mut [&mut self.last_focused_id],
rdom, rdom,
rdom.resolve_maybe_id(*root), rdom.element_to_node_id(*id),
), ),
_ => (), _ => (),
} }
} }
} }
pub(crate) fn set_focus(&mut self, rdom: &mut Dom, id: RealNodeId) { pub(crate) fn set_focus(&mut self, rdom: &mut TuiDom, id: RealNodeId) {
if let Some(old) = self.last_focused_id.replace(id) { if let Some(old) = self.last_focused_id.replace(id) {
rdom[old].state.focused = false; rdom[old].state.focused = false;
} }
+88 -81
View File
@@ -2,7 +2,8 @@ use crossterm::event::{
Event as TermEvent, KeyCode as TermKeyCode, KeyModifiers, MouseButton, MouseEventKind, Event as TermEvent, KeyCode as TermKeyCode, KeyModifiers, MouseButton, MouseEventKind,
}; };
use dioxus_core::*; use dioxus_core::*;
use dioxus_native_core::RealNodeId; use dioxus_native_core::tree::TreeView;
use dioxus_native_core::NodeId;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use dioxus_html::geometry::euclid::{Point2D, Rect, Size2D}; use dioxus_html::geometry::euclid::{Point2D, Rect, Size2D};
@@ -12,19 +13,25 @@ use dioxus_html::geometry::{
use dioxus_html::input_data::keyboard_types::{Code, Key, Location, Modifiers}; use dioxus_html::input_data::keyboard_types::{Code, Key, Location, Modifiers};
use dioxus_html::input_data::MouseButtonSet as DioxusMouseButtons; use dioxus_html::input_data::MouseButtonSet as DioxusMouseButtons;
use dioxus_html::input_data::{MouseButton as DioxusMouseButton, MouseButtonSet}; use dioxus_html::input_data::{MouseButton as DioxusMouseButton, MouseButtonSet};
use dioxus_html::{event_bubbles, on::*}; use dioxus_html::{event_bubbles, FocusData, KeyboardData, MouseData, WheelData};
use std::{ use std::{
any::Any, any::Any,
cell::{RefCell, RefMut}, cell::{RefCell, RefMut},
rc::Rc, rc::Rc,
sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use taffy::geometry::{Point, Size}; use taffy::geometry::{Point, Size};
use taffy::{prelude::Layout, Taffy}; use taffy::{prelude::Layout, Taffy};
use crate::FocusState; use crate::FocusState;
use crate::{Dom, Node}; use crate::{TuiDom, TuiNode};
pub(crate) struct Event {
pub id: ElementId,
pub name: &'static str,
pub data: Rc<dyn Any>,
pub bubbles: bool,
}
// a wrapper around the input state for easier access // a wrapper around the input state for easier access
// todo: fix loop // todo: fix loop
@@ -71,12 +78,12 @@ enum EventData {
Keyboard(KeyboardData), Keyboard(KeyboardData),
} }
impl EventData { impl EventData {
fn into_any(self) -> Arc<dyn Any + Send + Sync> { fn into_any(self) -> Rc<dyn Any + Send + Sync> {
match self { match self {
Self::Mouse(m) => Arc::new(m), Self::Mouse(m) => Rc::new(m),
Self::Wheel(w) => Arc::new(w), Self::Wheel(w) => Rc::new(w),
Self::Screen(s) => Arc::new(s), Self::Screen(s) => Rc::new(s),
Self::Keyboard(k) => Arc::new(k), Self::Keyboard(k) => Rc::new(k),
} }
} }
} }
@@ -164,9 +171,9 @@ impl InnerInputState {
fn update( fn update(
&mut self, &mut self,
evts: &mut Vec<EventCore>, evts: &mut Vec<EventCore>,
resolved_events: &mut Vec<UserEvent>, resolved_events: &mut Vec<Event>,
layout: &Taffy, layout: &Taffy,
dom: &mut Dom, dom: &mut TuiDom,
) { ) {
let previous_mouse = self.mouse.clone(); let previous_mouse = self.mouse.clone();
@@ -192,33 +199,33 @@ impl InnerInputState {
if old_focus != self.focus_state.last_focused_id { if old_focus != self.focus_state.last_focused_id {
// elements with listeners will always have a element id // elements with listeners will always have a element id
if let Some(RealNodeId::ElementId(id)) = self.focus_state.last_focused_id { if let Some(id) = self.focus_state.last_focused_id {
resolved_events.push(UserEvent { let element = dom.tree.get(id).unwrap();
scope_id: None, if let Some(id) = element.node_data.element_id {
priority: EventPriority::Medium, resolved_events.push(Event {
name: "focus", name: "focus",
element: Some(id), id,
data: Arc::new(FocusData {}), data: Rc::new(FocusData {}),
bubbles: event_bubbles("focus"), bubbles: event_bubbles("focus"),
}); });
resolved_events.push(UserEvent { resolved_events.push(Event {
scope_id: None, name: "focusin",
priority: EventPriority::Medium, id,
name: "focusin", data: Rc::new(FocusData {}),
element: Some(id), bubbles: event_bubbles("focusin"),
data: Arc::new(FocusData {}), });
bubbles: event_bubbles("focusin"), }
});
} }
if let Some(RealNodeId::ElementId(id)) = old_focus { if let Some(id) = old_focus {
resolved_events.push(UserEvent { let element = dom.tree.get(id).unwrap();
scope_id: None, if let Some(id) = element.node_data.element_id {
priority: EventPriority::Medium, resolved_events.push(Event {
name: "focusout", name: "focusout",
element: Some(id), id,
data: Arc::new(FocusData {}), data: Rc::new(FocusData {}),
bubbles: event_bubbles("focusout"), bubbles: event_bubbles("focusout"),
}); });
}
} }
} }
@@ -230,9 +237,9 @@ impl InnerInputState {
fn resolve_mouse_events( fn resolve_mouse_events(
&mut self, &mut self,
previous_mouse: Option<MouseData>, previous_mouse: Option<MouseData>,
resolved_events: &mut Vec<UserEvent>, resolved_events: &mut Vec<Event>,
layout: &Taffy, layout: &Taffy,
dom: &mut Dom, dom: &mut TuiDom,
) { ) {
fn layout_contains_point(layout: &Layout, point: ScreenPoint) -> bool { fn layout_contains_point(layout: &Layout, point: ScreenPoint) -> bool {
let Point { x, y } = layout.location; let Point { x, y } = layout.location;
@@ -244,28 +251,29 @@ impl InnerInputState {
fn try_create_event( fn try_create_event(
name: &'static str, name: &'static str,
data: Arc<dyn Any + Send + Sync>, data: Rc<dyn Any>,
will_bubble: &mut FxHashSet<RealNodeId>, will_bubble: &mut FxHashSet<NodeId>,
resolved_events: &mut Vec<UserEvent>, resolved_events: &mut Vec<Event>,
node: &Node, node: &TuiNode,
dom: &Dom, dom: &TuiDom,
) { ) {
// only trigger event if the event was not triggered already by a child // only trigger event if the event was not triggered already by a child
let id = node.mounted_id(); let id = node.node_data.node_id;
if will_bubble.insert(id) { if will_bubble.insert(id) {
let mut parent = node.node_data.parent; let mut parent = dom.parent(id);
while let Some(parent_id) = parent { while let Some(current_parent) = parent {
let parent_id = current_parent.node_data.node_id;
will_bubble.insert(parent_id); will_bubble.insert(parent_id);
parent = dom[parent_id].node_data.parent; parent = dom.parent(parent_id);
}
if let Some(id) = node.mounted_id() {
resolved_events.push(Event {
name,
id,
data,
bubbles: event_bubbles(name),
})
} }
resolved_events.push(UserEvent {
scope_id: None,
priority: EventPriority::Medium,
name,
element: Some(id.as_element_id()),
data,
bubbles: event_bubbles(name),
})
} }
} }
@@ -326,7 +334,7 @@ impl InnerInputState {
if currently_contains && previously_contained { if currently_contains && previously_contained {
try_create_event( try_create_event(
"mousemove", "mousemove",
Arc::new(prepare_mouse_data(mouse_data, &node_layout)), Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -350,7 +358,7 @@ impl InnerInputState {
if currently_contains && !previously_contained { if currently_contains && !previously_contained {
try_create_event( try_create_event(
"mouseenter", "mouseenter",
Arc::new(mouse_data.clone()), Rc::new(mouse_data.clone()),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -373,7 +381,7 @@ impl InnerInputState {
if currently_contains && !previously_contained { if currently_contains && !previously_contained {
try_create_event( try_create_event(
"mouseover", "mouseover",
Arc::new(prepare_mouse_data(mouse_data, &node_layout)), Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -393,7 +401,7 @@ impl InnerInputState {
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"mousedown", "mousedown",
Arc::new(prepare_mouse_data(mouse_data, &node_layout)), Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -414,7 +422,7 @@ impl InnerInputState {
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"mouseup", "mouseup",
Arc::new(prepare_mouse_data(mouse_data, &node_layout)), Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -436,7 +444,7 @@ impl InnerInputState {
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"click", "click",
Arc::new(prepare_mouse_data(mouse_data, &node_layout)), Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -459,7 +467,7 @@ impl InnerInputState {
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"contextmenu", "contextmenu",
Arc::new(prepare_mouse_data(mouse_data, &node_layout)), Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -483,7 +491,7 @@ impl InnerInputState {
if currently_contains { if currently_contains {
try_create_event( try_create_event(
"wheel", "wheel",
Arc::new(w.clone()), Rc::new(w.clone()),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -508,7 +516,7 @@ impl InnerInputState {
if !currently_contains && previously_contained { if !currently_contains && previously_contained {
try_create_event( try_create_event(
"mouseleave", "mouseleave",
Arc::new(prepare_mouse_data(mouse_data, &node_layout)), Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -531,7 +539,7 @@ impl InnerInputState {
if !currently_contains && previously_contained { if !currently_contains && previously_contained {
try_create_event( try_create_event(
"mouseout", "mouseout",
Arc::new(prepare_mouse_data(mouse_data, &node_layout)), Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
&mut will_bubble, &mut will_bubble,
resolved_events, resolved_events,
node, node,
@@ -549,7 +557,7 @@ impl InnerInputState {
let currently_contains = layout_contains_point(node_layout, new_pos); let currently_contains = layout_contains_point(node_layout, new_pos);
if currently_contains && node.state.focus.level.focusable() { if currently_contains && node.state.focus.level.focusable() {
focus_id = Some(node.mounted_id()); focus_id = Some(node.node_data.node_id);
} }
}); });
if let Some(id) = focus_id { if let Some(id) = focus_id {
@@ -564,12 +572,11 @@ impl InnerInputState {
// } // }
} }
fn get_abs_layout(node: &Node, dom: &Dom, taffy: &Taffy) -> Layout { fn get_abs_layout(node: &TuiNode, dom: &TuiDom, taffy: &Taffy) -> Layout {
let mut node_layout = *taffy.layout(node.state.layout.node.unwrap()).unwrap(); let mut node_layout = *taffy.layout(node.state.layout.node.unwrap()).unwrap();
let mut current = node; let mut current = node;
while let Some(parent_id) = current.node_data.parent { while let Some(parent) = dom.parent(current.node_data.node_id) {
let parent = &dom[parent_id];
current = parent; current = parent;
let parent_layout = taffy.layout(parent.state.layout.node.unwrap()).unwrap(); let parent_layout = taffy.layout(parent.state.layout.node.unwrap()).unwrap();
node_layout.location.x += parent_layout.location.x; node_layout.location.x += parent_layout.location.x;
@@ -614,11 +621,11 @@ impl RinkInputHandler {
) )
} }
pub(crate) fn prune(&self, mutations: &dioxus_core::Mutations, rdom: &Dom) { pub(crate) fn prune(&self, mutations: &dioxus_core::Mutations, rdom: &TuiDom) {
self.state.borrow_mut().focus_state.prune(mutations, rdom); self.state.borrow_mut().focus_state.prune(mutations, rdom);
} }
pub(crate) fn get_events(&self, layout: &Taffy, dom: &mut Dom) -> Vec<UserEvent> { pub(crate) fn get_events(&self, layout: &Taffy, dom: &mut TuiDom) -> Vec<Event> {
let mut resolved_events = Vec::new(); let mut resolved_events = Vec::new();
(*self.state).borrow_mut().update( (*self.state).borrow_mut().update(
@@ -651,7 +658,7 @@ impl RinkInputHandler {
}) })
.map(|evt| (evt.0, evt.1.into_any())); .map(|evt| (evt.0, evt.1.into_any()));
let mut hm: FxHashMap<&'static str, Vec<Arc<dyn Any + Send + Sync>>> = FxHashMap::default(); let mut hm: FxHashMap<&'static str, Vec<Rc<dyn Any + Send + Sync>>> = FxHashMap::default();
for (event, data) in events { for (event, data) in events {
if let Some(v) = hm.get_mut(event) { if let Some(v) = hm.get_mut(event) {
v.push(data); v.push(data);
@@ -663,14 +670,14 @@ impl RinkInputHandler {
for node in dom.get_listening_sorted(event) { for node in dom.get_listening_sorted(event) {
for data in &datas { for data in &datas {
if node.state.focused { if node.state.focused {
resolved_events.push(UserEvent { if let Some(id) = node.mounted_id() {
scope_id: None, resolved_events.push(Event {
priority: EventPriority::Medium, name: event,
name: event, id,
element: Some(node.mounted_id().as_element_id()), data: data.clone(),
data: data.clone(), bubbles: event_bubbles(event),
bubbles: event_bubbles(event), });
}); }
} }
} }
} }
+10 -12
View File
@@ -1,12 +1,10 @@
use std::cell::RefCell; use std::sync::{Arc, Mutex};
use std::rc::Rc;
use dioxus_core::*; use dioxus_core::*;
use dioxus_native_core::layout_attributes::apply_layout_attributes; use dioxus_native_core::layout_attributes::apply_layout_attributes;
use dioxus_native_core::node::OwnedAttributeView;
use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView}; use dioxus_native_core::node_ref::{AttributeMask, NodeMask, NodeView};
use dioxus_native_core::real_dom::OwnedAttributeView;
use dioxus_native_core::state::ChildDepState; use dioxus_native_core::state::ChildDepState;
use dioxus_native_core::RealNodeId;
use dioxus_native_core_macro::sorted_str_slice; use dioxus_native_core_macro::sorted_str_slice;
use taffy::prelude::*; use taffy::prelude::*;
@@ -42,8 +40,8 @@ pub(crate) struct TaffyLayout {
} }
impl ChildDepState for TaffyLayout { impl ChildDepState for TaffyLayout {
type Ctx = Rc<RefCell<Taffy>>; type Ctx = Arc<Mutex<Taffy>>;
type DepState = Self; type DepState = (Self,);
// use tag to force this to be called when a node is built // use tag to force this to be called when a node is built
const NODE_MASK: NodeMask = const NODE_MASK: NodeMask =
NodeMask::new_with_attrs(AttributeMask::Static(SORTED_LAYOUT_ATTRS)) NodeMask::new_with_attrs(AttributeMask::Static(SORTED_LAYOUT_ATTRS))
@@ -54,14 +52,14 @@ impl ChildDepState for TaffyLayout {
fn reduce<'a>( fn reduce<'a>(
&mut self, &mut self,
node: NodeView, node: NodeView,
children: impl Iterator<Item = &'a Self::DepState>, children: impl Iterator<Item = (&'a Self,)>,
ctx: &Self::Ctx, ctx: &Self::Ctx,
) -> bool ) -> bool
where where
Self::DepState: 'a, Self::DepState: 'a,
{ {
let mut changed = false; let mut changed = false;
let mut taffy = ctx.borrow_mut(); let mut taffy = ctx.lock().expect("poisoned taffy");
let mut style = Style::default(); let mut style = Style::default();
if let Some(text) = node.text() { if let Some(text) = node.text() {
let char_len = text.chars().count(); let char_len = text.chars().count();
@@ -81,7 +79,7 @@ impl ChildDepState for TaffyLayout {
taffy.set_style(n, style).unwrap(); taffy.set_style(n, style).unwrap();
} }
} else { } else {
self.node = PossiblyUninitalized::Initialized(taffy.new_node(style, &[]).unwrap()); self.node = PossiblyUninitalized::Initialized(taffy.new_leaf(style).unwrap());
changed = true; changed = true;
} }
} else { } else {
@@ -101,14 +99,14 @@ impl ChildDepState for TaffyLayout {
} }
// the root node fills the entire area // the root node fills the entire area
if node.id() == RealNodeId::ElementId(ElementId(0)) { if node.id() == Some(ElementId(0)) {
apply_layout_attributes("width", "100%", &mut style); apply_layout_attributes("width", "100%", &mut style);
apply_layout_attributes("height", "100%", &mut style); apply_layout_attributes("height", "100%", &mut style);
} }
// Set all direct nodes as our children // Set all direct nodes as our children
let mut child_layout = vec![]; let mut child_layout = vec![];
for l in children { for (l,) in children {
child_layout.push(l.node.unwrap()); child_layout.push(l.node.unwrap());
} }
@@ -121,7 +119,7 @@ impl ChildDepState for TaffyLayout {
} }
} else { } else {
self.node = PossiblyUninitalized::Initialized( self.node = PossiblyUninitalized::Initialized(
taffy.new_node(style, &child_layout).unwrap(), taffy.new_with_children(style, &child_layout).unwrap(),
); );
changed = true; changed = true;
} }
+28 -33
View File
@@ -1,24 +1,23 @@
use anyhow::Result; use anyhow::Result;
use anymap::AnyMap;
use crossterm::{ use crossterm::{
event::{DisableMouseCapture, EnableMouseCapture, Event as TermEvent, KeyCode, KeyModifiers}, event::{DisableMouseCapture, EnableMouseCapture, Event as TermEvent, KeyCode, KeyModifiers},
execute, execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
}; };
use dioxus_core::exports::futures_channel::mpsc::unbounded; use futures_channel::mpsc::unbounded;
use dioxus_core::*; use dioxus_core::*;
use dioxus_native_core::{real_dom::RealDom, RealNodeId}; use dioxus_native_core::{real_dom::RealDom, NodeId, SendAnyMap, FxDashSet};
use focus::FocusState; use focus::FocusState;
use futures::{ use futures::{
channel::mpsc::{UnboundedReceiver, UnboundedSender}, channel::mpsc::{UnboundedReceiver, UnboundedSender},
pin_mut, StreamExt, pin_mut, StreamExt,
}; };
use query::Query; use query::Query;
use std::cell::RefCell; use std::{cell::RefCell, sync::{Mutex, Arc}};
use std::rc::Rc; use std::rc::Rc;
use std::{io, time::Duration}; use std::{io, time::Duration};
use taffy::Taffy; use taffy::Taffy;
pub use taffy::{geometry::Point, prelude::Size}; pub use taffy::{geometry::Point, prelude::*};
use tui::{backend::CrosstermBackend, layout::Rect, Terminal}; use tui::{backend::CrosstermBackend, layout::Rect, Terminal};
mod config; mod config;
@@ -80,10 +79,10 @@ pub fn launch_cfg(app: Component<()>, cfg: Config) {
let cx = dom.base_scope(); let cx = dom.base_scope();
let rdom = Rc::new(RefCell::new(RealDom::new())); let rdom = Rc::new(RefCell::new(RealDom::new()));
let taffy = Rc::new(RefCell::new(Taffy::new())); let taffy = Arc::new(Mutex::new(Taffy::new()));
cx.provide_root_context(state); cx.provide_context(state);
cx.provide_root_context(TuiContext { tx: event_tx_clone }); cx.provide_context(TuiContext { tx: event_tx_clone });
cx.provide_root_context(Query { cx.provide_context(Query {
rdom: rdom.clone(), rdom: rdom.clone(),
stretch: taffy.clone(), stretch: taffy.clone(),
}); });
@@ -91,8 +90,8 @@ pub fn launch_cfg(app: Component<()>, cfg: Config) {
{ {
let mut rdom = rdom.borrow_mut(); let mut rdom = rdom.borrow_mut();
let mutations = dom.rebuild(); let mutations = dom.rebuild();
let to_update = rdom.apply_mutations(vec![mutations]); let to_update = rdom.apply_mutations(mutations);
let mut any_map = AnyMap::new(); let mut any_map = SendAnyMap::new();
any_map.insert(taffy.clone()); any_map.insert(taffy.clone());
let _to_rerender = rdom.update_state(to_update, any_map); let _to_rerender = rdom.update_state(to_update, any_map);
} }
@@ -114,8 +113,8 @@ fn render_vdom(
mut event_reciever: UnboundedReceiver<InputEvent>, mut event_reciever: UnboundedReceiver<InputEvent>,
handler: RinkInputHandler, handler: RinkInputHandler,
cfg: Config, cfg: Config,
rdom: Rc<RefCell<Dom>>, rdom: Rc<RefCell<TuiDom>>,
taffy: Rc<RefCell<Taffy>>, taffy: Arc<Mutex<Taffy>>,
mut register_event: impl FnMut(crossterm::event::Event), mut register_event: impl FnMut(crossterm::event::Event),
) -> Result<()> { ) -> Result<()> {
tokio::runtime::Builder::new_current_thread() tokio::runtime::Builder::new_current_thread()
@@ -133,10 +132,8 @@ fn render_vdom(
terminal.clear().unwrap(); terminal.clear().unwrap();
} }
let mut to_rerender: rustc_hash::FxHashSet<RealNodeId> = let mut to_rerender =FxDashSet::default();
vec![RealNodeId::ElementId(ElementId(0))] to_rerender.insert(NodeId(0));
.into_iter()
.collect();
let mut updated = true; let mut updated = true;
loop { loop {
@@ -153,17 +150,17 @@ fn render_vdom(
if !to_rerender.is_empty() || updated { if !to_rerender.is_empty() || updated {
updated = false; updated = false;
fn resize(dims: Rect, taffy: &mut Taffy, rdom: &Dom) { fn resize(dims: Rect, taffy: &mut Taffy, rdom: &TuiDom) {
let width = dims.width; let width = dims.width;
let height = dims.height; let height = dims.height;
let root_node = rdom[ElementId(0)].state.layout.node.unwrap(); let root_node = rdom[NodeId(0)].state.layout.node.unwrap();
taffy taffy
.compute_layout( .compute_layout(
root_node, root_node,
Size { Size {
width: taffy::prelude::Number::Defined((width - 1) as f32), width: AvailableSpace::Definite((width - 1) as f32),
height: taffy::prelude::Number::Defined((height - 1) as f32), height: AvailableSpace::Definite((height - 1) as f32),
}, },
) )
.unwrap(); .unwrap();
@@ -172,15 +169,15 @@ fn render_vdom(
terminal.draw(|frame| { terminal.draw(|frame| {
let rdom = rdom.borrow(); let rdom = rdom.borrow();
// size is guaranteed to not change when rendering // size is guaranteed to not change when rendering
resize(frame.size(), &mut taffy.borrow_mut(), &rdom); resize(frame.size(), &mut taffy.lock().expect("taffy lock poisoned"), &rdom);
let root = &rdom[ElementId(0)]; let root = &rdom[NodeId(0)];
render::render_vnode( render::render_vnode(
frame, frame,
&taffy.borrow(), &taffy.lock().expect("taffy lock poisoned"),
&rdom, &rdom,
root, root,
cfg, cfg,
Point::zero(), Point::ZERO,
); );
})?; })?;
} else { } else {
@@ -192,7 +189,7 @@ fn render_vdom(
width: 100, width: 100,
height: 100, height: 100,
}, },
&mut taffy.borrow_mut(), &mut taffy.lock().expect("taffy lock poisoned"),
&rdom, &rdom,
); );
} }
@@ -234,23 +231,21 @@ fn render_vdom(
{ {
let evts = { let evts = {
let mut rdom = rdom.borrow_mut(); let mut rdom = rdom.borrow_mut();
handler.get_events(&taffy.borrow(), &mut rdom) handler.get_events(&taffy.lock().expect("taffy lock poisoned"), &mut rdom)
}; };
{ {
updated |= handler.state().focus_state.clean(); updated |= handler.state().focus_state.clean();
} }
for e in evts { for e in evts {
vdom.handle_message(SchedulerMsg::Event(e)); vdom.handle_event(e.name, e.data, e.id, e.bubbles)
} }
let mut rdom = rdom.borrow_mut(); let mut rdom = rdom.borrow_mut();
let mutations = vdom.work_with_deadline(|| false); let mutations = vdom.render_immediate();
for m in &mutations { handler.prune(&mutations, &rdom);
handler.prune(m, &rdom);
}
// updates the dom's nodes // updates the dom's nodes
let to_update = rdom.apply_mutations(mutations); let to_update = rdom.apply_mutations(mutations);
// update the style and layout // update the style and layout
let mut any_map = AnyMap::new(); let mut any_map = SendAnyMap::new();
any_map.insert(taffy.clone()); any_map.insert(taffy.clone());
to_rerender = rdom.update_state(to_update, any_map); to_rerender = rdom.update_state(to_update, any_map);
} }
+5 -4
View File
@@ -4,12 +4,12 @@ use crate::style_attributes::StyleModifier;
use dioxus_native_core::{real_dom::RealDom, state::*}; use dioxus_native_core::{real_dom::RealDom, state::*};
use dioxus_native_core_macro::{sorted_str_slice, State}; use dioxus_native_core_macro::{sorted_str_slice, State};
pub(crate) type Dom = RealDom<NodeState>; pub(crate) type TuiDom = RealDom<NodeState>;
pub(crate) type Node = dioxus_native_core::real_dom::Node<NodeState>; pub(crate) type TuiNode = dioxus_native_core::node::Node<NodeState>;
#[derive(Debug, Clone, State, Default)] #[derive(Debug, Clone, State, Default)]
pub(crate) struct NodeState { pub(crate) struct NodeState {
#[child_dep_state(layout, RefCell<Stretch>)] #[child_dep_state(layout, Mutex<Stretch>)]
pub layout: TaffyLayout, pub layout: TaffyLayout,
#[parent_dep_state(style)] #[parent_dep_state(style)]
pub style: StyleModifier, pub style: StyleModifier,
@@ -45,7 +45,8 @@ impl Default for PreventDefault {
} }
} }
impl NodeDepState<()> for PreventDefault { impl NodeDepState for PreventDefault {
type DepState = ();
type Ctx = (); type Ctx = ();
const NODE_MASK: dioxus_native_core::node_ref::NodeMask = const NODE_MASK: dioxus_native_core::node_ref::NodeMask =
+12 -7
View File
@@ -1,6 +1,7 @@
use std::{ use std::{
cell::{Ref, RefCell}, cell::{Ref, RefCell},
rc::Rc, rc::Rc,
sync::{Arc, Mutex, MutexGuard},
}; };
use dioxus_core::ElementId; use dioxus_core::ElementId;
@@ -10,7 +11,7 @@ use taffy::{
Taffy, Taffy,
}; };
use crate::Dom; use crate::TuiDom;
/// Allows querying the layout of nodes after rendering. It will only provide a correct value after a node is rendered. /// Allows querying the layout of nodes after rendering. It will only provide a correct value after a node is rendered.
/// Provided as a root context for all tui applictions. /// Provided as a root context for all tui applictions.
@@ -45,24 +46,28 @@ use crate::Dom;
/// ``` /// ```
#[derive(Clone)] #[derive(Clone)]
pub struct Query { pub struct Query {
pub(crate) rdom: Rc<RefCell<Dom>>, pub(crate) rdom: Rc<RefCell<TuiDom>>,
pub(crate) stretch: Rc<RefCell<Taffy>>, pub(crate) stretch: Arc<Mutex<Taffy>>,
} }
impl Query { impl Query {
pub fn get(&self, id: ElementId) -> ElementRef { pub fn get(&self, id: ElementId) -> ElementRef {
ElementRef::new(self.rdom.borrow(), self.stretch.borrow(), id) ElementRef::new(
self.rdom.borrow(),
self.stretch.lock().expect("taffy lock poisoned"),
id,
)
} }
} }
pub struct ElementRef<'a> { pub struct ElementRef<'a> {
inner: Ref<'a, Dom>, inner: Ref<'a, TuiDom>,
stretch: Ref<'a, Taffy>, stretch: MutexGuard<'a, Taffy>,
id: ElementId, id: ElementId,
} }
impl<'a> ElementRef<'a> { impl<'a> ElementRef<'a> {
fn new(inner: Ref<'a, Dom>, stretch: Ref<'a, Taffy>, id: ElementId) -> Self { fn new(inner: Ref<'a, TuiDom>, stretch: MutexGuard<'a, Taffy>, id: ElementId) -> Self {
Self { inner, stretch, id } Self { inner, stretch, id }
} }
+8 -7
View File
@@ -1,3 +1,4 @@
use dioxus_native_core::tree::TreeView;
use std::io::Stdout; use std::io::Stdout;
use taffy::{ use taffy::{
geometry::Point, geometry::Point,
@@ -10,7 +11,7 @@ use crate::{
style::{RinkColor, RinkStyle}, style::{RinkColor, RinkStyle},
style_attributes::{BorderEdge, BorderStyle}, style_attributes::{BorderEdge, BorderStyle},
widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext}, widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext},
Config, Dom, Node, Config, TuiDom, TuiNode,
}; };
const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5]; const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5];
@@ -18,12 +19,12 @@ const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5];
pub(crate) fn render_vnode( pub(crate) fn render_vnode(
frame: &mut tui::Frame<CrosstermBackend<Stdout>>, frame: &mut tui::Frame<CrosstermBackend<Stdout>>,
layout: &Taffy, layout: &Taffy,
rdom: &Dom, rdom: &TuiDom,
node: &Node, node: &TuiNode,
cfg: Config, cfg: Config,
parent_location: Point<f32>, parent_location: Point<f32>,
) { ) {
use dioxus_native_core::real_dom::NodeType; use dioxus_native_core::node::NodeType;
if let NodeType::Placeholder = &node.node_data.node_type { if let NodeType::Placeholder = &node.node_data.node_type {
return; return;
@@ -68,7 +69,7 @@ pub(crate) fn render_vnode(
frame.render_widget(WidgetWithContext::new(label, cfg), area); frame.render_widget(WidgetWithContext::new(label, cfg), area);
} }
} }
NodeType::Element { children, .. } => { NodeType::Element { .. } => {
let area = Rect::new(x as u16, y as u16, *width as u16, *height as u16); let area = Rect::new(x as u16, y as u16, *width as u16, *height as u16);
// the renderer will panic if a node is rendered out of range even if the size is zero // the renderer will panic if a node is rendered out of range even if the size is zero
@@ -76,7 +77,7 @@ pub(crate) fn render_vnode(
frame.render_widget(WidgetWithContext::new(node, cfg), area); frame.render_widget(WidgetWithContext::new(node, cfg), area);
} }
for c in children { for c in rdom.children_ids(node.node_data.node_id).unwrap() {
render_vnode(frame, layout, rdom, &rdom[*c], cfg, location); render_vnode(frame, layout, rdom, &rdom[*c], cfg, location);
} }
} }
@@ -84,7 +85,7 @@ pub(crate) fn render_vnode(
} }
} }
impl RinkWidget for &Node { impl RinkWidget for &TuiNode {
fn render(self, area: Rect, mut buf: RinkBuffer<'_>) { fn render(self, area: Rect, mut buf: RinkBuffer<'_>) {
use tui::symbols::line::*; use tui::symbols::line::*;
+4 -4
View File
@@ -31,8 +31,8 @@
use dioxus_native_core::{ use dioxus_native_core::{
layout_attributes::parse_value, layout_attributes::parse_value,
node::OwnedAttributeView,
node_ref::{AttributeMask, NodeMask, NodeView}, node_ref::{AttributeMask, NodeMask, NodeView},
real_dom::OwnedAttributeView,
state::ParentDepState, state::ParentDepState,
}; };
use dioxus_native_core_macro::sorted_str_slice; use dioxus_native_core_macro::sorted_str_slice;
@@ -48,12 +48,12 @@ pub struct StyleModifier {
impl ParentDepState for StyleModifier { impl ParentDepState for StyleModifier {
type Ctx = (); type Ctx = ();
type DepState = Self; type DepState = (Self,);
// todo: seperate each attribute into it's own class // todo: seperate each attribute into it's own class
const NODE_MASK: NodeMask = const NODE_MASK: NodeMask =
NodeMask::new_with_attrs(AttributeMask::Static(SORTED_STYLE_ATTRS)).with_element(); NodeMask::new_with_attrs(AttributeMask::Static(SORTED_STYLE_ATTRS)).with_element();
fn reduce(&mut self, node: NodeView, parent: Option<&Self::DepState>, _: &Self::Ctx) -> bool { fn reduce(&mut self, node: NodeView, parent: Option<(&Self,)>, _: &Self::Ctx) -> bool {
let mut new = StyleModifier::default(); let mut new = StyleModifier::default();
if parent.is_some() { if parent.is_some() {
new.core.fg = None; new.core.fg = None;
@@ -91,7 +91,7 @@ impl ParentDepState for StyleModifier {
} }
// keep the text styling from the parent element // keep the text styling from the parent element
if let Some(parent) = parent { if let Some((parent,)) = parent {
let mut new_style = new.core.merge(parent.core); let mut new_style = new.core.merge(parent.core);
new_style.bg = new.core.bg; new_style.bg = new.core.bg;
new.core = new_style; new.core = new_style;