element.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. use std::{
  2. any::Any,
  3. fmt::{Display, Formatter},
  4. };
  5. use dioxus_core::{ElementId, Mutations, VirtualDom};
  6. use dioxus_html::{
  7. geometry::euclid::{Point2D, Rect, Size2D},
  8. MountedData, MountedError, RenderedElementBacking,
  9. };
  10. use dioxus_native_core::NodeId;
  11. use plasmo::query::{ElementRef, Query};
  12. pub(crate) fn find_mount_events(mutations: &Mutations) -> Vec<ElementId> {
  13. let mut mount_events = Vec::new();
  14. for mutation in &mutations.edits {
  15. if let dioxus_core::Mutation::NewEventListener {
  16. name: "mounted",
  17. id,
  18. } = mutation
  19. {
  20. mount_events.push(*id);
  21. }
  22. }
  23. mount_events
  24. }
  25. // We need to queue the mounted events to give rink time to rendere and resolve the layout of elements after they are created
  26. pub(crate) fn create_mounted_events(
  27. vdom: &VirtualDom,
  28. events: &mut Vec<(ElementId, &'static str, Box<dyn Any>, bool)>,
  29. mount_events: impl Iterator<Item = (ElementId, NodeId)>,
  30. ) {
  31. let query: Query = vdom
  32. .base_scope()
  33. .consume_context()
  34. .expect("Query should be in context");
  35. for (id, node_id) in mount_events {
  36. let element = TuiElement {
  37. query: query.clone(),
  38. id: node_id,
  39. };
  40. events.push((id, "mounted", Box::new(MountedData::new(element)), false));
  41. }
  42. }
  43. #[derive(Clone)]
  44. pub(crate) struct TuiElement {
  45. query: Query,
  46. id: NodeId,
  47. }
  48. impl TuiElement {
  49. pub(crate) fn element(&self) -> ElementRef {
  50. self.query.get(self.id)
  51. }
  52. }
  53. impl RenderedElementBacking for TuiElement {
  54. fn get_client_rect(
  55. &self,
  56. ) -> std::pin::Pin<
  57. Box<
  58. dyn futures::Future<
  59. Output = dioxus_html::MountedResult<dioxus_html::geometry::euclid::Rect<f64, f64>>,
  60. >,
  61. >,
  62. > {
  63. let layout = self.element().layout();
  64. Box::pin(async move {
  65. match layout {
  66. Some(layout) => {
  67. let x = layout.location.x as f64;
  68. let y = layout.location.y as f64;
  69. let width = layout.size.width as f64;
  70. let height = layout.size.height as f64;
  71. Ok(Rect::new(Point2D::new(x, y), Size2D::new(width, height)))
  72. }
  73. None => Err(MountedError::OperationFailed(Box::new(TuiElementNotFound))),
  74. }
  75. })
  76. }
  77. fn as_any(&self) -> &dyn std::any::Any {
  78. self
  79. }
  80. }
  81. #[derive(Debug)]
  82. struct TuiElementNotFound;
  83. impl Display for TuiElementNotFound {
  84. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  85. write!(f, "TUI element not found")
  86. }
  87. }
  88. impl std::error::Error for TuiElementNotFound {}