mouse.rs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. use crate::geometry::{ClientPoint, Coordinates, ElementPoint, PagePoint, ScreenPoint};
  2. use crate::input_data::{MouseButton, MouseButtonSet};
  3. use crate::prelude::*;
  4. use dioxus_core::Event;
  5. use keyboard_types::Modifiers;
  6. pub type MouseEvent = Event<MouseData>;
  7. /// A synthetic event that wraps a web-style [`MouseEvent`](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent)
  8. /// Data associated with a mouse event
  9. pub struct MouseData {
  10. inner: Box<dyn HasMouseData>,
  11. }
  12. impl<E: HasMouseData + 'static> From<E> for MouseData {
  13. fn from(e: E) -> Self {
  14. Self { inner: Box::new(e) }
  15. }
  16. }
  17. impl std::fmt::Debug for MouseData {
  18. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  19. f.debug_struct("MouseData")
  20. .field("coordinates", &self.coordinates())
  21. .field("modifiers", &self.modifiers())
  22. .field("held_buttons", &self.held_buttons())
  23. .field("trigger_button", &self.trigger_button())
  24. .finish()
  25. }
  26. }
  27. impl<E: HasMouseData> PartialEq<E> for MouseData {
  28. fn eq(&self, other: &E) -> bool {
  29. self.coordinates() == other.coordinates()
  30. && self.modifiers() == other.modifiers()
  31. && self.held_buttons() == other.held_buttons()
  32. && self.trigger_button() == other.trigger_button()
  33. }
  34. }
  35. /// A trait for any object that has the data for a mouse event
  36. pub trait HasMouseData: PointerInteraction {
  37. /// return self as Any
  38. fn as_any(&self) -> &dyn std::any::Any;
  39. }
  40. impl_event! {
  41. MouseData;
  42. /// Execute a callback when a button is clicked.
  43. ///
  44. /// ## Description
  45. ///
  46. /// An element receives a click event when a pointing device button (such as a mouse's primary mouse button)
  47. /// is both pressed and released while the pointer is located inside the element.
  48. ///
  49. /// - Bubbles: Yes
  50. /// - Cancelable: Yes
  51. /// - Interface(InteData): [`MouseEvent`]
  52. ///
  53. /// If the button is pressed on one element and the pointer is moved outside the element before the button
  54. /// is released, the event is fired on the most specific ancestor element that contained both elements.
  55. /// `click` fires after both the `mousedown` and `mouseup` events have fired, in that order.
  56. ///
  57. /// ## Example
  58. /// ```rust, ignore
  59. /// rsx!( button { onclick: move |_| tracing::info!("Clicked!"), "click me" } )
  60. /// ```
  61. ///
  62. /// ## Reference
  63. /// - <https://www.w3schools.com/tags/ev_onclick.asp>
  64. /// - <https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event>
  65. onclick
  66. /// oncontextmenu
  67. oncontextmenu
  68. #[deprecated(since = "0.5.0", note = "use ondoubleclick instead")]
  69. ondblclick
  70. ondoubleclick: "ondblclick"
  71. /// onmousedown
  72. onmousedown
  73. /// onmouseenter
  74. onmouseenter
  75. /// onmouseleave
  76. onmouseleave
  77. /// onmousemove
  78. onmousemove
  79. /// onmouseout
  80. onmouseout
  81. /// onmouseover
  82. ///
  83. /// Triggered when the users's mouse hovers over an element.
  84. onmouseover
  85. /// onmouseup
  86. onmouseup
  87. }
  88. impl MouseData {
  89. /// Create a new instance of MouseData
  90. pub fn new(inner: impl HasMouseData + 'static) -> Self {
  91. Self {
  92. inner: Box::new(inner),
  93. }
  94. }
  95. /// Downcast this event to a concrete event type
  96. #[inline(always)]
  97. pub fn downcast<T: 'static>(&self) -> Option<&T> {
  98. self.inner.as_any().downcast_ref::<T>()
  99. }
  100. }
  101. impl InteractionLocation for MouseData {
  102. fn client_coordinates(&self) -> ClientPoint {
  103. self.inner.client_coordinates()
  104. }
  105. fn page_coordinates(&self) -> PagePoint {
  106. self.inner.page_coordinates()
  107. }
  108. fn screen_coordinates(&self) -> ScreenPoint {
  109. self.inner.screen_coordinates()
  110. }
  111. }
  112. impl InteractionElementOffset for MouseData {
  113. fn element_coordinates(&self) -> ElementPoint {
  114. self.inner.element_coordinates()
  115. }
  116. fn coordinates(&self) -> Coordinates {
  117. self.inner.coordinates()
  118. }
  119. }
  120. impl ModifiersInteraction for MouseData {
  121. /// The set of modifier keys which were pressed when the event occurred
  122. fn modifiers(&self) -> Modifiers {
  123. self.inner.modifiers()
  124. }
  125. }
  126. impl PointerInteraction for MouseData {
  127. /// The set of mouse buttons which were held when the event occurred.
  128. fn held_buttons(&self) -> MouseButtonSet {
  129. self.inner.held_buttons()
  130. }
  131. /// The mouse button that triggered the event
  132. ///
  133. // todo the following is kind of bad; should we just return None when the trigger_button is unreliable (and frankly irrelevant)? i guess we would need the event_type here
  134. /// This is only guaranteed to indicate which button was pressed during events caused by pressing or releasing a button. As such, it is not reliable for events such as mouseenter, mouseleave, mouseover, mouseout, or mousemove. For example, a value of MouseButton::Primary may also indicate that no button was pressed.
  135. fn trigger_button(&self) -> Option<MouseButton> {
  136. self.inner.trigger_button()
  137. }
  138. }
  139. impl PartialEq for MouseData {
  140. fn eq(&self, other: &Self) -> bool {
  141. self.coordinates() == other.coordinates()
  142. && self.modifiers() == other.modifiers()
  143. && self.held_buttons() == other.held_buttons()
  144. && self.trigger_button() == other.trigger_button()
  145. }
  146. }
  147. #[cfg(feature = "serialize")]
  148. /// A serialized version of [`MouseData`]
  149. #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Clone, Default)]
  150. pub struct SerializedMouseData {
  151. /// Common data for all pointer/mouse events
  152. #[serde(flatten)]
  153. point_data: crate::point_interaction::SerializedPointInteraction,
  154. }
  155. #[cfg(feature = "serialize")]
  156. impl SerializedMouseData {
  157. /// Create a new instance of SerializedMouseData
  158. pub fn new(
  159. trigger_button: Option<MouseButton>,
  160. held_buttons: MouseButtonSet,
  161. coordinates: Coordinates,
  162. modifiers: Modifiers,
  163. ) -> Self {
  164. Self {
  165. point_data: crate::point_interaction::SerializedPointInteraction::new(
  166. trigger_button,
  167. held_buttons,
  168. coordinates,
  169. modifiers,
  170. ),
  171. }
  172. }
  173. }
  174. #[cfg(feature = "serialize")]
  175. impl From<&MouseData> for SerializedMouseData {
  176. fn from(e: &MouseData) -> Self {
  177. Self {
  178. point_data: crate::point_interaction::SerializedPointInteraction::from(e),
  179. }
  180. }
  181. }
  182. #[cfg(feature = "serialize")]
  183. impl HasMouseData for SerializedMouseData {
  184. fn as_any(&self) -> &dyn std::any::Any {
  185. self
  186. }
  187. }
  188. #[cfg(feature = "serialize")]
  189. impl InteractionLocation for SerializedMouseData {
  190. fn client_coordinates(&self) -> ClientPoint {
  191. self.point_data.client_coordinates()
  192. }
  193. fn page_coordinates(&self) -> PagePoint {
  194. self.point_data.page_coordinates()
  195. }
  196. fn screen_coordinates(&self) -> ScreenPoint {
  197. self.point_data.screen_coordinates()
  198. }
  199. }
  200. #[cfg(feature = "serialize")]
  201. impl InteractionElementOffset for SerializedMouseData {
  202. fn element_coordinates(&self) -> ElementPoint {
  203. self.point_data.element_coordinates()
  204. }
  205. }
  206. #[cfg(feature = "serialize")]
  207. impl ModifiersInteraction for SerializedMouseData {
  208. fn modifiers(&self) -> Modifiers {
  209. self.point_data.modifiers()
  210. }
  211. }
  212. #[cfg(feature = "serialize")]
  213. impl PointerInteraction for SerializedMouseData {
  214. fn held_buttons(&self) -> MouseButtonSet {
  215. self.point_data.held_buttons()
  216. }
  217. fn trigger_button(&self) -> Option<MouseButton> {
  218. self.point_data.trigger_button()
  219. }
  220. }
  221. #[cfg(feature = "serialize")]
  222. impl serde::Serialize for MouseData {
  223. fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
  224. SerializedMouseData::from(self).serialize(serializer)
  225. }
  226. }
  227. #[cfg(feature = "serialize")]
  228. impl<'de> serde::Deserialize<'de> for MouseData {
  229. fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
  230. let data = SerializedMouseData::deserialize(deserializer)?;
  231. Ok(Self {
  232. inner: Box::new(data),
  233. })
  234. }
  235. }