implement mounted event for TUI

This commit is contained in:
Evan Almloff committed 2023-03-23 17:33:27 -05:00
1 parent 8243dfe00d
commit e0d46d9820
2 files changed
+102

No files matched your search

+92
View File
@@ -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 {}
+10
View File
@@ -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());