bugfixes, testing and refactoring

This commit is contained in:
Evan Almloff committed 2022-03-26 20:32:49 -05:00
1 parent 6adfa8805c
commit 7f4e257757
20 files changed
+3888 -739

No files matched your search

+22 -19
View File
@@ -2,14 +2,17 @@ use crossterm::event::{
Event as TermEvent, KeyCode as TermKeyCode, KeyModifiers, MouseButton, MouseEventKind,
};
use dioxus_core::*;
use fxhash::{FxHashMap, FxHashSet};
use dioxus_html::{on::*, KeyCode};
use dioxus_native_core::{layout::StretchLayout, Tree, TreeNode};
use dioxus_native_core::{
client_tree::{ClientTree, TreeNode},
layout::StretchLayout,
};
use futures::{channel::mpsc::UnboundedReceiver, StreamExt};
use std::{
any::Any,
cell::RefCell,
collections::{HashMap, HashSet},
rc::Rc,
sync::Arc,
time::{Duration, Instant},
@@ -166,7 +169,7 @@ impl InnerInputState {
evts: &mut Vec<EventCore>,
resolved_events: &mut Vec<UserEvent>,
layout: &Stretch,
tree: &mut Tree<StretchLayout, StyleModifier>,
tree: &mut ClientTree<StretchLayout, StyleModifier>,
) {
let previous_mouse = self
.mouse
@@ -191,7 +194,7 @@ impl InnerInputState {
previous_mouse: Option<(MouseData, Vec<u16>)>,
resolved_events: &mut Vec<UserEvent>,
layout: &Stretch,
tree: &mut Tree<StretchLayout, StyleModifier>,
tree: &mut ClientTree<StretchLayout, StyleModifier>,
) {
struct Data<'b> {
new_pos: (i32, i32),
@@ -213,17 +216,17 @@ impl InnerInputState {
fn try_create_event(
name: &'static str,
data: Arc<dyn Any + Send + Sync>,
will_bubble: &mut HashSet<ElementId>,
will_bubble: &mut FxHashSet<ElementId>,
resolved_events: &mut Vec<UserEvent>,
node: &TreeNode<StretchLayout, StyleModifier>,
tree: &Tree<StretchLayout, StyleModifier>,
tree: &ClientTree<StretchLayout, StyleModifier>,
) {
// only trigger event if the event was not triggered already by a child
if will_bubble.insert(node.id) {
let mut parent = node.parent;
while let Some(parent_id) = parent {
will_bubble.insert(parent_id);
parent = tree.get(parent_id.0).parent;
parent = tree[parent_id.0].parent;
}
resolved_events.push(UserEvent {
scope_id: None,
@@ -259,7 +262,7 @@ impl InnerInputState {
{
// mousemove
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("mousemove") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let previously_contained = data
@@ -285,7 +288,7 @@ impl InnerInputState {
{
// mouseenter
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("mouseenter") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let previously_contained = data
@@ -311,7 +314,7 @@ impl InnerInputState {
{
// mouseover
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("mouseover") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let previously_contained = data
@@ -337,7 +340,7 @@ impl InnerInputState {
{
// mousedown
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("mousedown") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos);
@@ -359,7 +362,7 @@ impl InnerInputState {
{
// mouseup
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("mouseup") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos);
@@ -381,7 +384,7 @@ impl InnerInputState {
{
// click
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("click") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos);
@@ -403,7 +406,7 @@ impl InnerInputState {
{
// contextmenu
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("contextmenu") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos);
@@ -425,7 +428,7 @@ impl InnerInputState {
{
// wheel
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("wheel") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let currently_contains = layout_contains_point(node_layout, data.new_pos);
@@ -449,7 +452,7 @@ impl InnerInputState {
{
// mouseleave
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("mouseleave") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let previously_contained = data
@@ -473,7 +476,7 @@ impl InnerInputState {
{
// mouseout
let mut will_bubble = HashSet::new();
let mut will_bubble = FxHashSet::default();
for node in tree.get_listening_sorted("mouseout") {
let node_layout = layout.layout(node.up_state.node.unwrap()).unwrap();
let previously_contained = data
@@ -543,7 +546,7 @@ impl RinkInputHandler {
pub fn get_events<'a>(
&self,
layout: &Stretch,
tree: &mut Tree<StretchLayout, StyleModifier>,
tree: &mut ClientTree<StretchLayout, StyleModifier>,
) -> Vec<UserEvent> {
let mut resolved_events = Vec::new();
@@ -578,7 +581,7 @@ impl RinkInputHandler {
.map(|evt| (evt.0, evt.1.into_any()));
// todo: currently resolves events in all nodes, but once the focus system is added it should filter by focus
let mut hm: HashMap<&'static str, Vec<Arc<dyn Any + Send + Sync>>> = HashMap::new();
let mut hm: FxHashMap<&'static str, Vec<Arc<dyn Any + Send + Sync>>> = FxHashMap::default();
for (event, data) in events {
if let Some(v) = hm.get_mut(event) {
v.push(data);
+12 -32
View File
@@ -9,10 +9,8 @@ use crossterm::{
};
use dioxus_core::exports::futures_channel::mpsc::unbounded;
use dioxus_core::*;
use dioxus_html::on::{KeyboardData, MouseData, PointerData, TouchData, WheelData};
use dioxus_native_core::{layout::StretchLayout, Tree};
use dioxus_native_core::{client_tree::ClientTree, layout::StretchLayout};
use futures::{channel::mpsc::UnboundedSender, pin_mut, StreamExt};
use std::collections::HashSet;
use std::{io, time::Duration};
use stretch2::{prelude::Size, Stretch};
use style_attributes::StyleModifier;
@@ -44,7 +42,7 @@ pub fn launch_cfg(app: Component<()>, cfg: Config) {
cx.provide_root_context(state);
let mut tree: Tree<StretchLayout, StyleModifier> = Tree::new();
let mut tree: ClientTree<StretchLayout, StyleModifier> = ClientTree::new();
let mutations = dom.rebuild();
let to_update = tree.apply_mutations(vec![mutations]);
let mut stretch = Stretch::new();
@@ -60,7 +58,7 @@ pub fn render_vdom(
ctx: UnboundedSender<TermEvent>,
handler: RinkInputHandler,
cfg: Config,
mut tree: Tree<StretchLayout, StyleModifier>,
mut tree: ClientTree<StretchLayout, StyleModifier>,
mut stretch: Stretch,
) -> Result<()> {
// Setup input handling
@@ -100,12 +98,8 @@ pub fn render_vdom(
let mut terminal = Terminal::new(backend).unwrap();
terminal.clear().unwrap();
let mut to_rerender: HashSet<usize> = tree
.nodes
.iter()
.filter_map(|n| n.as_ref())
.map(|n| n.id.0)
.collect();
let mut to_rerender: fxhash::FxHashSet<usize> = vec![0].into_iter().collect();
let mut redraw = true;
loop {
/*
@@ -120,15 +114,16 @@ pub fn render_vdom(
todo: lazy re-rendering
*/
if !to_rerender.is_empty() {
if !to_rerender.is_empty() || redraw {
redraw = false;
terminal.draw(|frame| {
// size is guaranteed to not change when rendering
let dims = frame.size();
// println!("{dims:?}");
let width = dims.width;
let height = dims.height;
let root_id = tree.root;
let root_node = tree.get(root_id).up_state.node.unwrap();
let root_id = tree.root_id();
let root_node = tree[root_id].up_state.node.unwrap();
stretch
.compute_layout(
root_node,
@@ -138,7 +133,7 @@ pub fn render_vdom(
},
)
.unwrap();
let root = tree.get(tree.root);
let root = &tree[tree.root_id()];
render::render_vnode(frame, &stretch, &tree, &root, cfg);
})?;
}
@@ -146,22 +141,6 @@ pub fn render_vdom(
// resolve events before rendering
// todo: events do not trigger update?
for e in handler.get_events(&stretch, &mut tree) {
// let tname = if e.data.is::<PointerData>() {
// "PointerData"
// } else if e.data.is::<WheelData>() {
// "WheelData"
// } else if e.data.is::<MouseData>() {
// "MouseData"
// } else if e.data.is::<KeyboardData>() {
// "KeyboardData"
// } else if e.data.is::<TouchData>() {
// "TouchData"
// } else if e.data.is::<(u16, u16)>() {
// "(u16, u16)"
// } else {
// panic!()
// };
// println!("{tname}: {e:?}");
vdom.handle_message(SchedulerMsg::Event(e));
}
@@ -184,7 +163,8 @@ pub fn render_vdom(
break;
}
}
TermEvent::Resize(_, _) | TermEvent::Mouse(_) => {}
TermEvent::Resize(_, _) => redraw = true,
TermEvent::Mouse(_) => {}
},
InputEvent::Tick => {} // tick
InputEvent::Close => break,
+13 -7
View File
@@ -1,4 +1,8 @@
use dioxus_native_core::{layout::StretchLayout, layout_attributes::UnitSystem, Tree, TreeNode};
use dioxus_native_core::{
client_tree::{ClientTree, TreeNode},
layout::StretchLayout,
layout_attributes::UnitSystem,
};
use std::io::Stdout;
use stretch2::{
geometry::Point,
@@ -19,12 +23,14 @@ const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5];
pub fn render_vnode<'a>(
frame: &mut tui::Frame<CrosstermBackend<Stdout>>,
layout: &Stretch,
tree: &Tree<StretchLayout, StyleModifier>,
tree: &ClientTree<StretchLayout, StyleModifier>,
node: &TreeNode<StretchLayout, StyleModifier>,
cfg: Config,
) {
use dioxus_native_core::client_tree::TreeNodeType;
match &node.node_type {
dioxus_native_core::TreeNodeType::Placeholder => return,
TreeNodeType::Placeholder => return,
_ => (),
}
@@ -34,7 +40,7 @@ pub fn render_vnode<'a>(
let Size { width, height } = size;
match &node.node_type {
dioxus_native_core::TreeNodeType::Text { text } => {
TreeNodeType::Text { text } => {
#[derive(Default)]
struct Label<'a> {
text: &'a str,
@@ -64,7 +70,7 @@ pub fn render_vnode<'a>(
frame.render_widget(WidgetWithContext::new(label, cfg), area);
}
}
dioxus_native_core::TreeNodeType::Element { children, .. } => {
TreeNodeType::Element { children, .. } => {
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
@@ -73,10 +79,10 @@ pub fn render_vnode<'a>(
}
for c in children {
render_vnode(frame, layout, tree, tree.get(c.0), cfg);
render_vnode(frame, layout, tree, &tree[c.0], cfg);
}
}
dioxus_native_core::TreeNodeType::Placeholder => unreachable!(),
TreeNodeType::Placeholder => unreachable!(),
}
}
+4 -2
View File
@@ -31,8 +31,8 @@
use dioxus_core::{Attribute, VNode};
use dioxus_native_core::{
client_tree::PushedDownState,
layout_attributes::{parse_value, UnitSystem},
PushedDownState,
};
use crate::style::{RinkColor, RinkStyle};
@@ -48,7 +48,9 @@ impl PushedDownState for StyleModifier {
fn reduce(&mut self, parent: Option<&Self>, vnode: &VNode, _ctx: &mut Self::Ctx) {
*self = StyleModifier::default();
self.style.fg = None;
if parent.is_some() {
self.style.fg = None;
}
match vnode {
VNode::Element(el) => {
// handle text modifier elements
-83
View File
@@ -1,83 +0,0 @@
// use dioxus_core::{Element, ElementId, Mutations, VNode, VirtualDom, DomEdit};
// /// The focus system needs a iterator that can persist through changes in the [VirtualDom]. Iterate through it with [ElementIter::next], and update it with [ElementIter::update] (with data from [`VirtualDom::work_with_deadline`]).
// pub(crate) struct ElementIter {
// // stack of elements and fragments
// stack: smallvec::SmallVec<[(ElementId, usize); 5]>,
// }
// impl ElementIter {
// pub(crate) fn new(initial: ElementId) -> Self {
// ElementIter {
// stack: smallvec::smallvec![(initial, 0)],
// }
// }
// /// remove stale element refreneces
// pub(crate) fn update(&mut self, mutations: &Mutations, vdom: &VirtualDom) {
// let ids_removed: Vec<_> = mutations.edits.iter().filter_map(|e| if let DomEdit::Remove{root: }).collect();
// for node in self.stack {
// match node.0 {
// VNode::Fragment(f) => {
// }
// VNode::Element(_) => {}
// _ => unreachable!(),
// }
// }
// }
// pub(crate) fn next<'a>(&mut self, vdom: &'a VirtualDom) -> Option<&'a VNode<'a>> {
// let last = self.stack.last()?.0;
// let node = vdom.get_element(last)?;
// match node {
// VNode::Fragment(f) => {
// let mut last_mut = self.stack.last_mut()?;
// if last_mut.1 + 1 >= f.children.len() {
// self.stack.pop();
// self.next(vdom)
// } else {
// last_mut.1 += 1;
// let new_node = &f.children[last_mut.1];
// if matches!(new_node, VNode::Fragment(_) | VNode::Element(_)) {
// self.stack.push((new_node.mounted_id(), 0));
// }
// self.next(vdom)
// }
// }
// VNode::Component(vcomp) => {
// let idx = vcomp.scope.get().unwrap();
// let new_node = vdom.get_scope(idx).unwrap().root_node();
// *self.stack.last_mut()? = (new_node.mounted_id(), 0);
// self.next(vdom)
// }
// VNode::Placeholder(_) | VNode::Text(_) => {
// self.stack.pop();
// self.next(vdom)
// }
// VNode::Element(e) => {
// let mut last_mut = self.stack.last_mut()?;
// if last_mut.1 + 1 >= e.children.len() {
// self.stack.pop();
// self.next(vdom);
// } else {
// last_mut.1 += 1;
// let new_node = &e.children[last_mut.1];
// if matches!(new_node, VNode::Fragment(_) | VNode::Element(_)) {
// self.stack.push((new_node.mounted_id(), 0));
// }
// self.next(vdom);
// }
// Some(node)
// }
// }
// }
// pub(crate) fn peak(&self) -> Option<&ElementId> {
// self.stack.last().map(|(e, c)| e)
// }
// }