implement mounted event for TUI
This commit is contained in:
1 parent
8243dfe00d
commit
e0d46d9820
2 files changed
+102
No files matched your search
@@ -0,0 +1,92 @@
|
||||
use std::{
|
||||
fmt::{Display, Formatter},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use dioxus_core::{ElementId, Mutations, VirtualDom};
|
||||
use dioxus_html::{
|
||||
geometry::euclid::{Point2D, Rect, Size2D},
|
||||
MountedData, MountedError, RenderedElementBacking,
|
||||
};
|
||||
|
||||
use crate::query::{ElementRef, Query};
|
||||
|
||||
pub(crate) fn find_mount_events(mutations: &Mutations) -> Vec<ElementId> {
|
||||
let mut mount_events = Vec::new();
|
||||
for mutation in &mutations.edits {
|
||||
if let dioxus_core::Mutation::NewEventListener {
|
||||
name: "mounted",
|
||||
id,
|
||||
} = mutation
|
||||
{
|
||||
mount_events.push(*id);
|
||||
}
|
||||
}
|
||||
mount_events
|
||||
}
|
||||
|
||||
pub(crate) fn send_mounted_events(vdom: &mut VirtualDom, mount_events: Vec<ElementId>) {
|
||||
let query: Query = vdom
|
||||
.base_scope()
|
||||
.consume_context()
|
||||
.expect("Query should be in context");
|
||||
for id in mount_events {
|
||||
let element = TuiElement {
|
||||
query: query.clone(),
|
||||
id,
|
||||
};
|
||||
vdom.handle_event("mounted", Rc::new(MountedData::new(element)), id, false);
|
||||
}
|
||||
}
|
||||
|
||||
struct TuiElement {
|
||||
query: Query,
|
||||
id: ElementId,
|
||||
}
|
||||
|
||||
impl TuiElement {
|
||||
pub(crate) fn element(&self) -> ElementRef {
|
||||
self.query.get(self.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderedElementBacking for TuiElement {
|
||||
fn get_client_rect(
|
||||
&self,
|
||||
) -> std::pin::Pin<
|
||||
Box<
|
||||
dyn futures::Future<
|
||||
Output = dioxus_html::MountedResult<dioxus_html::geometry::euclid::Rect<f64, f64>>,
|
||||
>,
|
||||
>,
|
||||
> {
|
||||
let layout = self.element().layout();
|
||||
Box::pin(async move {
|
||||
match layout {
|
||||
Some(layout) => {
|
||||
let x = layout.location.x as f64;
|
||||
let y = layout.location.y as f64;
|
||||
let width = layout.size.width as f64;
|
||||
let height = layout.size.height as f64;
|
||||
Ok(Rect::new(Point2D::new(x, y), Size2D::new(width, height)))
|
||||
}
|
||||
None => Err(MountedError::OperationFailed(Box::new(TuiElementNotFound))),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn get_raw_element(&self) -> dioxus_html::MountedResult<&dyn std::any::Any> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TuiElementNotFound;
|
||||
|
||||
impl Display for TuiElementNotFound {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "TUI element not found")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for TuiElementNotFound {}
|
||||
@@ -7,6 +7,7 @@ use crossterm::{
|
||||
};
|
||||
use dioxus_core::*;
|
||||
use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, NodeMask, SendAnyMap};
|
||||
use element::{find_mount_events, send_mounted_events};
|
||||
use focus::FocusState;
|
||||
use futures::{
|
||||
channel::mpsc::{UnboundedReceiver, UnboundedSender},
|
||||
@@ -26,6 +27,7 @@ use tokio::select;
|
||||
use tui::{backend::CrosstermBackend, layout::Rect, Terminal};
|
||||
|
||||
mod config;
|
||||
mod element;
|
||||
mod focus;
|
||||
mod hooks;
|
||||
mod layout;
|
||||
@@ -114,7 +116,11 @@ pub fn launch_cfg_with_props<Props: 'static>(app: Component<Props>, props: Props
|
||||
{
|
||||
let mut rdom = rdom.borrow_mut();
|
||||
let mutations = dom.rebuild();
|
||||
// Search for mount events that happened during the rebuild
|
||||
let mounted = find_mount_events(&mutations);
|
||||
let (to_update, _) = rdom.apply_mutations(mutations);
|
||||
// Send the mount events
|
||||
send_mounted_events(&mut dom, mounted);
|
||||
let mut any_map = SendAnyMap::new();
|
||||
any_map.insert(taffy.clone());
|
||||
let _to_rerender = rdom.update_state(to_update, any_map);
|
||||
@@ -307,8 +313,12 @@ fn render_vdom(
|
||||
let mut rdom = rdom.borrow_mut();
|
||||
let mutations = vdom.render_immediate();
|
||||
handler.prune(&mutations, &rdom);
|
||||
// Search for mount events that happened during the rebuild
|
||||
let mounted = find_mount_events(&mutations);
|
||||
// updates the dom's nodes
|
||||
let (to_update, dirty) = rdom.apply_mutations(mutations);
|
||||
// Send the mount events
|
||||
send_mounted_events(vdom, mounted);
|
||||
// update the style and layout
|
||||
let mut any_map = SendAnyMap::new();
|
||||
any_map.insert(taffy.clone());
|
||||
|
||||
Reference in new issue
Block a user