mounted.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. //! Handles querying data from the renderer
  2. use euclid::Rect;
  3. use std::{
  4. fmt::{Display, Formatter},
  5. future::Future,
  6. pin::Pin,
  7. };
  8. /// An Element that has been rendered and allows reading and modifying information about it.
  9. ///
  10. /// Different platforms will have different implementations and different levels of support for this trait. Renderers that do not support specific features will return `None` for those queries.
  11. // we can not use async_trait here because it does not create a trait that is object safe
  12. pub trait RenderedElementBacking: std::any::Any {
  13. /// return self as Any
  14. fn as_any(&self) -> &dyn std::any::Any;
  15. /// Get the bounding rectangle of the element relative to the viewport (this does not include the scroll position)
  16. #[allow(clippy::type_complexity)]
  17. fn get_client_rect(&self) -> Pin<Box<dyn Future<Output = MountedResult<Rect<f64, f64>>>>> {
  18. Box::pin(async { Err(MountedError::NotSupported) })
  19. }
  20. /// Scroll to make the element visible
  21. fn scroll_to(
  22. &self,
  23. _behavior: ScrollBehavior,
  24. ) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
  25. Box::pin(async { Err(MountedError::NotSupported) })
  26. }
  27. /// Set the focus on the element
  28. fn set_focus(&self, _focus: bool) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
  29. Box::pin(async { Err(MountedError::NotSupported) })
  30. }
  31. }
  32. impl RenderedElementBacking for () {
  33. fn as_any(&self) -> &dyn std::any::Any {
  34. self
  35. }
  36. }
  37. /// The way that scrolling should be performed
  38. #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
  39. pub enum ScrollBehavior {
  40. /// Scroll to the element immediately
  41. #[cfg_attr(feature = "serialize", serde(rename = "instant"))]
  42. Instant,
  43. /// Scroll to the element smoothly
  44. #[cfg_attr(feature = "serialize", serde(rename = "smooth"))]
  45. Smooth,
  46. }
  47. /// An Element that has been rendered and allows reading and modifying information about it.
  48. ///
  49. /// Different platforms will have different implementations and different levels of support for this trait. Renderers that do not support specific features will return `None` for those queries.
  50. pub struct MountedData {
  51. inner: Box<dyn RenderedElementBacking>,
  52. }
  53. impl<E: RenderedElementBacking> From<E> for MountedData {
  54. fn from(e: E) -> Self {
  55. Self { inner: Box::new(e) }
  56. }
  57. }
  58. impl MountedData {
  59. /// Create a new MountedData
  60. pub fn new(registry: impl RenderedElementBacking + 'static) -> Self {
  61. Self {
  62. inner: Box::new(registry),
  63. }
  64. }
  65. /// Get the bounding rectangle of the element relative to the viewport (this does not include the scroll position)
  66. pub async fn get_client_rect(&self) -> MountedResult<Rect<f64, f64>> {
  67. self.inner.get_client_rect().await
  68. }
  69. /// Scroll to make the element visible
  70. pub fn scroll_to(
  71. &self,
  72. behavior: ScrollBehavior,
  73. ) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
  74. self.inner.scroll_to(behavior)
  75. }
  76. /// Set the focus on the element
  77. pub fn set_focus(&self, focus: bool) -> Pin<Box<dyn Future<Output = MountedResult<()>>>> {
  78. self.inner.set_focus(focus)
  79. }
  80. /// Downcast this event to a concrete event type
  81. pub fn downcast<T: 'static>(&self) -> Option<&T> {
  82. self.inner.as_any().downcast_ref::<T>()
  83. }
  84. }
  85. use dioxus_core::Event;
  86. pub type MountedEvent = Event<MountedData>;
  87. impl_event! [
  88. MountedData;
  89. /// mounted
  90. onmounted
  91. ];
  92. /// The MountedResult type for the MountedData
  93. pub type MountedResult<T> = Result<T, MountedError>;
  94. #[derive(Debug)]
  95. /// The error type for the MountedData
  96. #[non_exhaustive]
  97. pub enum MountedError {
  98. /// The renderer does not support the requested operation
  99. NotSupported,
  100. /// The element was not found
  101. OperationFailed(Box<dyn std::error::Error>),
  102. }
  103. impl Display for MountedError {
  104. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  105. match self {
  106. MountedError::NotSupported => {
  107. write!(f, "The renderer does not support the requested operation")
  108. }
  109. MountedError::OperationFailed(e) => {
  110. write!(f, "The operation failed: {}", e)
  111. }
  112. }
  113. }
  114. }
  115. impl std::error::Error for MountedError {}