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_core::*;
|
||||||
use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, NodeMask, SendAnyMap};
|
use dioxus_native_core::{real_dom::RealDom, FxDashSet, NodeId, NodeMask, SendAnyMap};
|
||||||
|
use element::{find_mount_events, send_mounted_events};
|
||||||
use focus::FocusState;
|
use focus::FocusState;
|
||||||
use futures::{
|
use futures::{
|
||||||
channel::mpsc::{UnboundedReceiver, UnboundedSender},
|
channel::mpsc::{UnboundedReceiver, UnboundedSender},
|
||||||
@@ -26,6 +27,7 @@ use tokio::select;
|
|||||||
use tui::{backend::CrosstermBackend, layout::Rect, Terminal};
|
use tui::{backend::CrosstermBackend, layout::Rect, Terminal};
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
mod element;
|
||||||
mod focus;
|
mod focus;
|
||||||
mod hooks;
|
mod hooks;
|
||||||
mod layout;
|
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 mut rdom = rdom.borrow_mut();
|
||||||
let mutations = dom.rebuild();
|
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);
|
let (to_update, _) = rdom.apply_mutations(mutations);
|
||||||
|
// Send the mount events
|
||||||
|
send_mounted_events(&mut dom, mounted);
|
||||||
let mut any_map = SendAnyMap::new();
|
let mut any_map = SendAnyMap::new();
|
||||||
any_map.insert(taffy.clone());
|
any_map.insert(taffy.clone());
|
||||||
let _to_rerender = rdom.update_state(to_update, any_map);
|
let _to_rerender = rdom.update_state(to_update, any_map);
|
||||||
@@ -307,8 +313,12 @@ fn render_vdom(
|
|||||||
let mut rdom = rdom.borrow_mut();
|
let mut rdom = rdom.borrow_mut();
|
||||||
let mutations = vdom.render_immediate();
|
let mutations = vdom.render_immediate();
|
||||||
handler.prune(&mutations, &rdom);
|
handler.prune(&mutations, &rdom);
|
||||||
|
// Search for mount events that happened during the rebuild
|
||||||
|
let mounted = find_mount_events(&mutations);
|
||||||
// updates the dom's nodes
|
// updates the dom's nodes
|
||||||
let (to_update, dirty) = rdom.apply_mutations(mutations);
|
let (to_update, dirty) = rdom.apply_mutations(mutations);
|
||||||
|
// Send the mount events
|
||||||
|
send_mounted_events(vdom, mounted);
|
||||||
// update the style and layout
|
// update the style and layout
|
||||||
let mut any_map = SendAnyMap::new();
|
let mut any_map = SendAnyMap::new();
|
||||||
any_map.insert(taffy.clone());
|
any_map.insert(taffy.clone());
|
||||||
|
|||||||
Reference in new issue
Block a user