feat: events bubble now

This commit is contained in:
Jonathan Kelley committed 2021-11-11 22:07:38 -05:00
1 parent b6262edd53
commit f2234068ba
6 files changed
+63 -57

No files matched your search

+4 -2
View File
@@ -12,6 +12,7 @@ use std::{
any::Any,
cell::{Cell, RefCell},
fmt::{Arguments, Debug, Formatter},
sync::Arc,
};
/// A composable "VirtualNode" to declare a User Interface in the Dioxus VirtualDOM.
@@ -366,7 +367,8 @@ pub struct Listener<'bump> {
pub event: &'static str,
/// The actual callback that the user specified
pub(crate) callback: RefCell<Option<BumpBox<'bump, dyn FnMut(Box<dyn Any + Send>) + 'bump>>>,
pub(crate) callback:
RefCell<Option<BumpBox<'bump, dyn FnMut(std::sync::Arc<dyn Any + Send + Sync>) + 'bump>>>,
}
/// Virtual Components for custom user-defined components
@@ -643,7 +645,7 @@ impl<'a> NodeFactory<'a> {
pub fn listener(
self,
event: &'static str,
callback: BumpBox<'a, dyn FnMut(Box<dyn Any + Send>) + 'a>,
callback: BumpBox<'a, dyn FnMut(Arc<dyn Any + Send + Sync>) + 'a>,
) -> Listener<'a> {
Listener {
mounted_node: Cell::new(None),
-24
View File
@@ -449,30 +449,6 @@ impl Scope {
self.generation.set(self.generation.get() + 1);
}
/// A safe wrapper around calling listeners
pub(crate) fn call_listener(&self, event: UserEvent, element: ElementId) {
let listners = &mut self.items.borrow_mut().listeners;
let listener = listners.iter().find(|lis| {
let search = lis;
if search.event == event.name {
let search_id = search.mounted_node.get();
search_id.map(|f| f == element).unwrap_or(false)
} else {
false
}
});
if let Some(listener) = listener {
let mut cb = listener.callback.borrow_mut();
if let Some(cb) = cb.as_mut() {
(cb)(event.event);
}
} else {
log::warn!("An event was triggered but there was no listener to handle it");
}
}
// General strategy here is to load up the appropriate suspended task and then run it.
// Suspended nodes cannot be called repeatedly.
pub(crate) fn call_suspended_node<'a>(&'a mut self, task_id: u64) {
+26 -1
View File
@@ -2,7 +2,10 @@ use bumpalo::Bump;
use futures_channel::mpsc::UnboundedSender;
use fxhash::FxHashMap;
use slab::Slab;
use std::cell::{Cell, RefCell};
use std::{
borrow::Borrow,
cell::{Cell, RefCell},
};
use crate::innerlude::*;
@@ -361,6 +364,28 @@ impl ScopeArena {
}
}
pub fn call_listener_with_bubbling(&self, event: UserEvent, element: ElementId) {
let nodes = self.nodes.borrow();
let mut cur_el = Some(element);
while let Some(id) = cur_el.take() {
if let Some(el) = nodes.get(id.0) {
let real_el = unsafe { &**el };
if let VNode::Element(real_el) = real_el {
for listener in real_el.listeners.borrow().iter() {
if listener.event == event.name {
let mut cb = listener.callback.borrow_mut();
if let Some(cb) = cb.as_mut() {
(cb)(event.event.clone());
}
}
}
cur_el = real_el.parent_id.get();
}
}
}
}
// The head of the bumpframe is the first linked NodeLink
pub fn wip_head(&self, id: &ScopeId) -> &VNode {
let scope = self.get_scope(id).unwrap();
+4 -4
View File
@@ -8,6 +8,8 @@ use futures_util::{Future, StreamExt};
use fxhash::FxHashSet;
use indexmap::IndexSet;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::Arc;
use std::task::Poll;
use std::{any::Any, collections::VecDeque};
@@ -402,9 +404,7 @@ impl VirtualDom {
log::info!("Calling listener {:?}, {:?}", event.scope_id, element);
if let Some(scope) = self.scopes.get_scope(&event.scope_id) {
// TODO: bubble properly here
scope.call_listener(event, element);
self.scopes.call_listener_with_bubbling(event, element);
while let Ok(Some(dirty_scope)) = self.receiver.try_next() {
self.pending_messages.push_front(dirty_scope);
}
@@ -644,7 +644,7 @@ pub struct UserEvent {
pub name: &'static str,
/// Event Data
pub event: Box<dyn Any + Send>,
pub event: Arc<dyn Any + Send + Sync>,
}
/// Priority of Event Triggers.