use euclid::Rect;
use std::{
fmt::{Display, Formatter},
future::Future,
pin::Pin,
};
pub trait RenderedElementBacking: std::any::Any {
fn as_any(&self) -> &dyn std::any::Any;
#[allow(clippy::type_complexity)]
fn get_client_rect(&self) -> Pin<Box<dyn Future<Output = MountedResult<Rect<f64, f64>>>>> {
Box::pin(async { Err(MountedError::NotSupported) })
}
fn scroll_to(
&self,
_behavior: ScrollBehavior,
) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
Box::pin(async { Err(MountedError::NotSupported) })
}
fn set_focus(&self, _focus: bool) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
Box::pin(async { Err(MountedError::NotSupported) })
}
}
impl RenderedElementBacking for () {
fn as_any(&self) -> &dyn std::any::Any {
self
}
}
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
pub enum ScrollBehavior {
#[cfg_attr(feature = "serialize", serde(rename = "instant"))]
Instant,
#[cfg_attr(feature = "serialize", serde(rename = "smooth"))]
Smooth,
}
pub struct MountedData {
inner: Box<dyn RenderedElementBacking>,
}
impl<E: RenderedElementBacking> From<E> for MountedData {
fn from(e: E) -> Self {
Self { inner: Box::new(e) }
}
}
impl MountedData {
pub fn new(registry: impl RenderedElementBacking + 'static) -> Self {
Self {
inner: Box::new(registry),
}
}
pub async fn get_client_rect(&self) -> MountedResult<Rect<f64, f64>> {
self.inner.get_client_rect().await
}
pub fn scroll_to(
&self,
behavior: ScrollBehavior,
) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
self.inner.scroll_to(behavior)
}
pub fn set_focus(&self, focus: bool) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
self.inner.set_focus(focus)
}
pub fn downcast<T: 'static>(&self) -> Option<&T> {
self.inner.as_any().downcast_ref::<T>()
}
}
use dioxus_core::Event;
pub type MountedEvent = Event<MountedData>;
impl_event! [
MountedData;
onmounted
];
pub type MountedResult<T> = Result<T, MountedError>;
#[derive(Debug)]
#[non_exhaustive]
pub enum MountedError {
NotSupported,
OperationFailed(Box<dyn std::error::Error>),
}
impl Display for MountedError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
MountedError::NotSupported => {
write!(f, "The renderer does not support the requested operation")
}
MountedError::OperationFailed(e) => {
write!(f, "The operation failed: {}", e)
}
}
}
}
impl std::error::Error for MountedError {}