events.rs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. use crate::{global_context::current_scope_id, Runtime, ScopeId};
  2. use generational_box::GenerationalBox;
  3. use std::{cell::Cell, rc::Rc};
  4. /// A wrapper around some generic data that handles the event's state
  5. ///
  6. ///
  7. /// Prevent this event from continuing to bubble up the tree to parent elements.
  8. ///
  9. /// # Example
  10. ///
  11. /// ```rust, ignore
  12. /// rsx! {
  13. /// button {
  14. /// onclick: move |evt: Event<MouseData>| {
  15. /// evt.cancel_bubble();
  16. ///
  17. /// }
  18. /// }
  19. /// }
  20. /// ```
  21. pub struct Event<T: 'static + ?Sized> {
  22. /// The data associated with this event
  23. pub data: Rc<T>,
  24. pub(crate) propagates: Rc<Cell<bool>>,
  25. }
  26. impl<T: ?Sized + 'static> Event<T> {
  27. pub(crate) fn new(data: Rc<T>, bubbles: bool) -> Self {
  28. Self {
  29. data,
  30. propagates: Rc::new(Cell::new(bubbles)),
  31. }
  32. }
  33. }
  34. impl<T> Event<T> {
  35. /// Map the event data to a new type
  36. ///
  37. /// # Example
  38. ///
  39. /// ```rust, ignore
  40. /// rsx! {
  41. /// button {
  42. /// onclick: move |evt: Event<FormData>| {
  43. /// let data = evt.map(|data| data.value());
  44. /// assert_eq!(data.inner(), "hello world");
  45. /// }
  46. /// }
  47. /// }
  48. /// ```
  49. pub fn map<U: 'static, F: FnOnce(&T) -> U>(&self, f: F) -> Event<U> {
  50. Event {
  51. data: Rc::new(f(&self.data)),
  52. propagates: self.propagates.clone(),
  53. }
  54. }
  55. /// Prevent this event from continuing to bubble up the tree to parent elements.
  56. ///
  57. /// # Example
  58. ///
  59. /// ```rust, ignore
  60. /// rsx! {
  61. /// button {
  62. /// onclick: move |evt: Event<MouseData>| {
  63. /// evt.cancel_bubble();
  64. /// }
  65. /// }
  66. /// }
  67. /// ```
  68. #[deprecated = "use stop_propagation instead"]
  69. pub fn cancel_bubble(&self) {
  70. self.propagates.set(false);
  71. }
  72. /// Prevent this event from continuing to bubble up the tree to parent elements.
  73. ///
  74. /// # Example
  75. ///
  76. /// ```rust, ignore
  77. /// rsx! {
  78. /// button {
  79. /// onclick: move |evt: Event<MouseData>| {
  80. /// evt.stop_propagation();
  81. /// }
  82. /// }
  83. /// }
  84. /// ```
  85. pub fn stop_propagation(&self) {
  86. self.propagates.set(false);
  87. }
  88. /// Get a reference to the inner data from this event
  89. ///
  90. /// ```rust, ignore
  91. /// rsx! {
  92. /// button {
  93. /// onclick: move |evt: Event<MouseData>| {
  94. /// let data = evt.inner.clone();
  95. /// cx.spawn(async move {
  96. /// println!("{:?}", data);
  97. /// });
  98. /// }
  99. /// }
  100. /// }
  101. /// ```
  102. pub fn data(&self) -> Rc<T> {
  103. self.data.clone()
  104. }
  105. }
  106. impl<T: ?Sized> Clone for Event<T> {
  107. fn clone(&self) -> Self {
  108. Self {
  109. propagates: self.propagates.clone(),
  110. data: self.data.clone(),
  111. }
  112. }
  113. }
  114. impl<T> std::ops::Deref for Event<T> {
  115. type Target = Rc<T>;
  116. fn deref(&self) -> &Self::Target {
  117. &self.data
  118. }
  119. }
  120. impl<T: std::fmt::Debug> std::fmt::Debug for Event<T> {
  121. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  122. f.debug_struct("UiEvent")
  123. .field("bubble_state", &self.propagates)
  124. .field("data", &self.data)
  125. .finish()
  126. }
  127. }
  128. /// The callback type generated by the `rsx!` macro when an `on` field is specified for components.
  129. ///
  130. /// This makes it possible to pass `move |evt| {}` style closures into components as property fields.
  131. ///
  132. ///
  133. /// # Example
  134. ///
  135. /// ```rust, ignore
  136. /// rsx!{
  137. /// MyComponent { onclick: move |evt| tracing::debug!("clicked") }
  138. /// }
  139. ///
  140. /// #[derive(Props)]
  141. /// struct MyProps {
  142. /// onclick: EventHandler<MouseEvent>,
  143. /// }
  144. ///
  145. /// fn MyComponent(cx: MyProps) -> Element {
  146. /// rsx!{
  147. /// button {
  148. /// onclick: move |evt| cx.onclick.call(evt),
  149. /// }
  150. /// }
  151. /// }
  152. ///
  153. /// ```
  154. pub struct EventHandler<T = ()> {
  155. pub(crate) origin: ScopeId,
  156. pub(super) callback: GenerationalBox<Option<ExternalListenerCallback<T>>>,
  157. }
  158. impl<T: 'static> Default for EventHandler<T> {
  159. fn default() -> Self {
  160. EventHandler::new(|_| {})
  161. }
  162. }
  163. impl<F: FnMut(T) + 'static, T: 'static> From<F> for EventHandler<T> {
  164. fn from(f: F) -> Self {
  165. EventHandler::new(f)
  166. }
  167. }
  168. impl<T> Copy for EventHandler<T> {}
  169. impl<T> Clone for EventHandler<T> {
  170. fn clone(&self) -> Self {
  171. *self
  172. }
  173. }
  174. impl<T: 'static> PartialEq for EventHandler<T> {
  175. fn eq(&self, _: &Self) -> bool {
  176. true
  177. }
  178. }
  179. type ExternalListenerCallback<T> = Box<dyn FnMut(T)>;
  180. impl<T: 'static> EventHandler<T> {
  181. /// Create a new [`EventHandler`] from an [`FnMut`]
  182. #[track_caller]
  183. pub fn new(mut f: impl FnMut(T) + 'static) -> EventHandler<T> {
  184. let callback = GenerationalBox::leak(Some(Box::new(move |event: T| {
  185. f(event);
  186. }) as Box<dyn FnMut(T)>));
  187. EventHandler {
  188. callback,
  189. origin: current_scope_id().expect("to be in a dioxus runtime"),
  190. }
  191. }
  192. /// Call this event handler with the appropriate event type
  193. ///
  194. /// This borrows the event using a RefCell. Recursively calling a listener will cause a panic.
  195. pub fn call(&self, event: T) {
  196. if let Some(callback) = self.callback.write().as_mut() {
  197. Runtime::with(|rt| rt.scope_stack.borrow_mut().push(self.origin));
  198. callback(event);
  199. Runtime::with(|rt| rt.scope_stack.borrow_mut().pop());
  200. }
  201. }
  202. /// Forcibly drop the internal handler callback, releasing memory
  203. ///
  204. /// This will force any future calls to "call" to not doing anything
  205. pub fn release(&self) {
  206. self.callback.set(None);
  207. }
  208. #[doc(hidden)]
  209. /// This should only be used by the `rsx!` macro.
  210. pub fn __set(&mut self, value: impl FnMut(T) + 'static) {
  211. self.callback.set(Some(Box::new(value)));
  212. }
  213. #[doc(hidden)]
  214. /// This should only be used by the `rsx!` macro.
  215. pub fn __take(&self) -> ExternalListenerCallback<T> {
  216. self.callback
  217. .manually_drop()
  218. .expect("Signal has already been dropped")
  219. .expect("EventHandler was manually dropped")
  220. }
  221. }
  222. impl<T: 'static> std::ops::Deref for EventHandler<T> {
  223. type Target = dyn Fn(T) + 'static;
  224. fn deref(&self) -> &Self::Target {
  225. // https://github.com/dtolnay/case-studies/tree/master/callable-types
  226. // First we create a closure that captures something with the Same in memory layout as Self (MaybeUninit<Self>).
  227. let uninit_callable = std::mem::MaybeUninit::<Self>::uninit();
  228. // Then move that value into the closure. We assume that the closure now has a in memory layout of Self.
  229. let uninit_closure = move |t| Self::call(unsafe { &*uninit_callable.as_ptr() }, t);
  230. // Check that the size of the closure is the same as the size of Self in case the compiler changed the layout of the closure.
  231. let size_of_closure = std::mem::size_of_val(&uninit_closure);
  232. assert_eq!(size_of_closure, std::mem::size_of::<Self>());
  233. // Then cast the lifetime of the closure to the lifetime of &self.
  234. fn cast_lifetime<'a, T>(_a: &T, b: &'a T) -> &'a T {
  235. b
  236. }
  237. let reference_to_closure = cast_lifetime(
  238. {
  239. // The real closure that we will never use.
  240. &uninit_closure
  241. },
  242. // We transmute self into a reference to the closure. This is safe because we know that the closure has the same memory layout as Self so &Closure == &Self.
  243. unsafe { std::mem::transmute(self) },
  244. );
  245. // Cast the closure to a trait object.
  246. reference_to_closure as &_
  247. }
  248. }