Implement new mutations with native core (#630)
* work on seperating tree struture from realdom * intial update to new mutations * handle height * update to taffy 0.2 * add as_varient functions to OwnedAttributeValue * make get node parent mut optionally return a parent * work on upward pass * add more code for parrellel passes * make resolve passes public * more work on parallel passes * fix deadlock and add more tests * move height into the tree instead of the realdom * make passes exicute in parallel instead of executing invidual passes in parellel * fix some warnings * add up dependant test * clean up examples * work on intigrating state with passes * update to new mutations * work on implementing macro * make the macro compile * more progress on macro * mark cloned nodes as dirty * update persistant_iterator utility * fix mask generation * update tui with new mutations * more progress updating tui * some basic tui examples working * don't push template nodes onto the stack * update hover example * update benchmark * update more examples * fix root node layout * ignore out of bounds renders * update color picker example * update all events example * update remaining examples * update tests * tests passing * move persistant iterator test * update examples * fix gaps in layout * fix formatting * fix memory leak
This commit is contained in:
1 parent
b9aad5e8f4
commit
67a6fa9eb8
38 files changed
+3405
-2417
No files matched your search
+97
-82
@@ -2,7 +2,8 @@ use crossterm::event::{
|
||||
Event as TermEvent, KeyCode as TermKeyCode, KeyModifiers, MouseButton, MouseEventKind,
|
||||
};
|
||||
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 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::MouseButtonSet as DioxusMouseButtons;
|
||||
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::{
|
||||
any::Any,
|
||||
cell::{RefCell, RefMut},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use taffy::geometry::{Point, Size};
|
||||
use taffy::{prelude::Layout, Taffy};
|
||||
|
||||
use crate::FocusState;
|
||||
use crate::{Dom, Node};
|
||||
use crate::{layout_to_screen_space, FocusState};
|
||||
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
|
||||
// todo: fix loop
|
||||
@@ -71,12 +78,12 @@ enum EventData {
|
||||
Keyboard(KeyboardData),
|
||||
}
|
||||
impl EventData {
|
||||
fn into_any(self) -> Arc<dyn Any + Send + Sync> {
|
||||
fn into_any(self) -> Rc<dyn Any + Send + Sync> {
|
||||
match self {
|
||||
Self::Mouse(m) => Arc::new(m),
|
||||
Self::Wheel(w) => Arc::new(w),
|
||||
Self::Screen(s) => Arc::new(s),
|
||||
Self::Keyboard(k) => Arc::new(k),
|
||||
Self::Mouse(m) => Rc::new(m),
|
||||
Self::Wheel(w) => Rc::new(w),
|
||||
Self::Screen(s) => Rc::new(s),
|
||||
Self::Keyboard(k) => Rc::new(k),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,9 +171,9 @@ impl InnerInputState {
|
||||
fn update(
|
||||
&mut self,
|
||||
evts: &mut Vec<EventCore>,
|
||||
resolved_events: &mut Vec<UserEvent>,
|
||||
resolved_events: &mut Vec<Event>,
|
||||
layout: &Taffy,
|
||||
dom: &mut Dom,
|
||||
dom: &mut TuiDom,
|
||||
) {
|
||||
let previous_mouse = self.mouse.clone();
|
||||
|
||||
@@ -192,33 +199,33 @@ impl InnerInputState {
|
||||
|
||||
if old_focus != self.focus_state.last_focused_id {
|
||||
// elements with listeners will always have a element id
|
||||
if let Some(RealNodeId::ElementId(id)) = self.focus_state.last_focused_id {
|
||||
resolved_events.push(UserEvent {
|
||||
scope_id: None,
|
||||
priority: EventPriority::Medium,
|
||||
name: "focus",
|
||||
element: Some(id),
|
||||
data: Arc::new(FocusData {}),
|
||||
bubbles: event_bubbles("focus"),
|
||||
});
|
||||
resolved_events.push(UserEvent {
|
||||
scope_id: None,
|
||||
priority: EventPriority::Medium,
|
||||
name: "focusin",
|
||||
element: Some(id),
|
||||
data: Arc::new(FocusData {}),
|
||||
bubbles: event_bubbles("focusin"),
|
||||
});
|
||||
if let Some(id) = self.focus_state.last_focused_id {
|
||||
let element = dom.tree.get(id).unwrap();
|
||||
if let Some(id) = element.node_data.element_id {
|
||||
resolved_events.push(Event {
|
||||
name: "focus",
|
||||
id,
|
||||
data: Rc::new(FocusData {}),
|
||||
bubbles: event_bubbles("focus"),
|
||||
});
|
||||
resolved_events.push(Event {
|
||||
name: "focusin",
|
||||
id,
|
||||
data: Rc::new(FocusData {}),
|
||||
bubbles: event_bubbles("focusin"),
|
||||
});
|
||||
}
|
||||
}
|
||||
if let Some(RealNodeId::ElementId(id)) = old_focus {
|
||||
resolved_events.push(UserEvent {
|
||||
scope_id: None,
|
||||
priority: EventPriority::Medium,
|
||||
name: "focusout",
|
||||
element: Some(id),
|
||||
data: Arc::new(FocusData {}),
|
||||
bubbles: event_bubbles("focusout"),
|
||||
});
|
||||
if let Some(id) = old_focus {
|
||||
let element = dom.tree.get(id).unwrap();
|
||||
if let Some(id) = element.node_data.element_id {
|
||||
resolved_events.push(Event {
|
||||
name: "focusout",
|
||||
id,
|
||||
data: Rc::new(FocusData {}),
|
||||
bubbles: event_bubbles("focusout"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,13 +237,21 @@ impl InnerInputState {
|
||||
fn resolve_mouse_events(
|
||||
&mut self,
|
||||
previous_mouse: Option<MouseData>,
|
||||
resolved_events: &mut Vec<UserEvent>,
|
||||
resolved_events: &mut Vec<Event>,
|
||||
layout: &Taffy,
|
||||
dom: &mut Dom,
|
||||
dom: &mut TuiDom,
|
||||
) {
|
||||
fn layout_contains_point(layout: &Layout, point: ScreenPoint) -> bool {
|
||||
let Point { x, y } = layout.location;
|
||||
let (x, y) = (
|
||||
layout_to_screen_space(x).round(),
|
||||
layout_to_screen_space(y).round(),
|
||||
);
|
||||
let Size { width, height } = layout.size;
|
||||
let (width, height) = (
|
||||
layout_to_screen_space(width).round(),
|
||||
layout_to_screen_space(height).round(),
|
||||
);
|
||||
|
||||
let layout_rect = Rect::new(Point2D::new(x, y), Size2D::new(width, height));
|
||||
layout_rect.contains(point.cast())
|
||||
@@ -244,28 +259,29 @@ impl InnerInputState {
|
||||
|
||||
fn try_create_event(
|
||||
name: &'static str,
|
||||
data: Arc<dyn Any + Send + Sync>,
|
||||
will_bubble: &mut FxHashSet<RealNodeId>,
|
||||
resolved_events: &mut Vec<UserEvent>,
|
||||
node: &Node,
|
||||
dom: &Dom,
|
||||
data: Rc<dyn Any>,
|
||||
will_bubble: &mut FxHashSet<NodeId>,
|
||||
resolved_events: &mut Vec<Event>,
|
||||
node: &TuiNode,
|
||||
dom: &TuiDom,
|
||||
) {
|
||||
// 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) {
|
||||
let mut parent = node.node_data.parent;
|
||||
while let Some(parent_id) = parent {
|
||||
let mut parent = dom.parent(id);
|
||||
while let Some(current_parent) = parent {
|
||||
let parent_id = current_parent.node_data.node_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 +342,7 @@ impl InnerInputState {
|
||||
if currently_contains && previously_contained {
|
||||
try_create_event(
|
||||
"mousemove",
|
||||
Arc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -350,7 +366,7 @@ impl InnerInputState {
|
||||
if currently_contains && !previously_contained {
|
||||
try_create_event(
|
||||
"mouseenter",
|
||||
Arc::new(mouse_data.clone()),
|
||||
Rc::new(mouse_data.clone()),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -373,7 +389,7 @@ impl InnerInputState {
|
||||
if currently_contains && !previously_contained {
|
||||
try_create_event(
|
||||
"mouseover",
|
||||
Arc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -393,7 +409,7 @@ impl InnerInputState {
|
||||
if currently_contains {
|
||||
try_create_event(
|
||||
"mousedown",
|
||||
Arc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -414,7 +430,7 @@ impl InnerInputState {
|
||||
if currently_contains {
|
||||
try_create_event(
|
||||
"mouseup",
|
||||
Arc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -436,7 +452,7 @@ impl InnerInputState {
|
||||
if currently_contains {
|
||||
try_create_event(
|
||||
"click",
|
||||
Arc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -459,7 +475,7 @@ impl InnerInputState {
|
||||
if currently_contains {
|
||||
try_create_event(
|
||||
"contextmenu",
|
||||
Arc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -483,7 +499,7 @@ impl InnerInputState {
|
||||
if currently_contains {
|
||||
try_create_event(
|
||||
"wheel",
|
||||
Arc::new(w.clone()),
|
||||
Rc::new(w.clone()),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -508,7 +524,7 @@ impl InnerInputState {
|
||||
if !currently_contains && previously_contained {
|
||||
try_create_event(
|
||||
"mouseleave",
|
||||
Arc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -531,7 +547,7 @@ impl InnerInputState {
|
||||
if !currently_contains && previously_contained {
|
||||
try_create_event(
|
||||
"mouseout",
|
||||
Arc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
Rc::new(prepare_mouse_data(mouse_data, &node_layout)),
|
||||
&mut will_bubble,
|
||||
resolved_events,
|
||||
node,
|
||||
@@ -549,7 +565,7 @@ impl InnerInputState {
|
||||
let currently_contains = layout_contains_point(node_layout, new_pos);
|
||||
|
||||
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 {
|
||||
@@ -564,12 +580,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 current = node;
|
||||
|
||||
while let Some(parent_id) = current.node_data.parent {
|
||||
let parent = &dom[parent_id];
|
||||
while let Some(parent) = dom.parent(current.node_data.node_id) {
|
||||
current = parent;
|
||||
let parent_layout = taffy.layout(parent.state.layout.node.unwrap()).unwrap();
|
||||
node_layout.location.x += parent_layout.location.x;
|
||||
@@ -614,11 +629,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);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
(*self.state).borrow_mut().update(
|
||||
@@ -651,7 +666,7 @@ impl RinkInputHandler {
|
||||
})
|
||||
.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 {
|
||||
if let Some(v) = hm.get_mut(event) {
|
||||
v.push(data);
|
||||
@@ -663,14 +678,14 @@ impl RinkInputHandler {
|
||||
for node in dom.get_listening_sorted(event) {
|
||||
for data in &datas {
|
||||
if node.state.focused {
|
||||
resolved_events.push(UserEvent {
|
||||
scope_id: None,
|
||||
priority: EventPriority::Medium,
|
||||
name: event,
|
||||
element: Some(node.mounted_id().as_element_id()),
|
||||
data: data.clone(),
|
||||
bubbles: event_bubbles(event),
|
||||
});
|
||||
if let Some(id) = node.mounted_id() {
|
||||
resolved_events.push(Event {
|
||||
name: event,
|
||||
id,
|
||||
data: data.clone(),
|
||||
bubbles: event_bubbles(event),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user