yew/virtual_dom/
listeners.rs1use std::rc::Rc;
2
3use crate::html::ImplicitClone;
4
5pub trait Listener {
8 fn kind(&self) -> ListenerKind;
10
11 fn handle(&self, event: web_sys::Event);
13
14 fn passive(&self) -> bool;
17}
18
19impl std::fmt::Debug for dyn Listener {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 write!(
22 f,
23 "Listener {{ kind: {}, passive: {:?} }}",
24 self.kind().as_ref(),
25 self.passive(),
26 )
27 }
28}
29
30macro_rules! gen_listener_kinds {
31 ($($kind:ident)*) => {
32 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
36 #[allow(non_camel_case_types)]
37 #[allow(missing_docs)]
38 pub enum ListenerKind {
39 $( $kind, )*
40 other(std::borrow::Cow<'static, str>),
41 }
42
43 impl ListenerKind {
44 pub fn type_name(&self) -> std::borrow::Cow<'static, str> {
45 match self {
46 Self::other(type_name) => type_name.clone(),
47 $( Self::$kind => stringify!($kind)[2..].into(), )*
48 }
49 }
50 }
51
52 impl AsRef<str> for ListenerKind {
53 fn as_ref(&self) -> &str {
54 match self {
55 $( Self::$kind => stringify!($kind), )*
56 Self::other(type_name) => type_name.as_ref(),
57 }
58 }
59 }
60 };
61}
62
63gen_listener_kinds! {
64 onabort
65 onauxclick
66 onblur
67 oncancel
68 oncanplay
69 oncanplaythrough
70 onchange
71 onclick
72 onclose
73 oncontextmenu
74 oncuechange
75 ondblclick
76 ondrag
77 ondragend
78 ondragenter
79 ondragexit
80 ondragleave
81 ondragover
82 ondragstart
83 ondrop
84 ondurationchange
85 onemptied
86 onended
87 onerror
88 onfocus
89 onfocusin
90 onfocusout
91 onformdata
92 oninput
93 oninvalid
94 onkeydown
95 onkeypress
96 onkeyup
97 onload
98 onloadeddata
99 onloadedmetadata
100 onloadstart
101 onmousedown
102 onmouseenter
103 onmouseleave
104 onmousemove
105 onmouseout
106 onmouseover
107 onmouseup
108 onpause
109 onplay
110 onplaying
111 onprogress
112 onratechange
113 onreset
114 onresize
115 onscroll
116 onsecuritypolicyviolation
117 onseeked
118 onseeking
119 onselect
120 onslotchange
121 onstalled
122 onsubmit
123 onsuspend
124 ontimeupdate
125 ontoggle
126 onvolumechange
127 onwaiting
128 onwheel
129 oncopy
130 oncut
131 onpaste
132 onanimationcancel
133 onanimationend
134 onanimationiteration
135 onanimationstart
136 ongotpointercapture
137 onloadend
138 onlostpointercapture
139 onpointercancel
140 onpointerdown
141 onpointerenter
142 onpointerleave
143 onpointerlockchange
144 onpointerlockerror
145 onpointermove
146 onpointerout
147 onpointerover
148 onpointerup
149 onselectionchange
150 onselectstart
151 onshow
152 ontouchcancel
153 ontouchend
154 ontouchmove
155 ontouchstart
156 ontransitioncancel
157 ontransitionend
158 ontransitionrun
159 ontransitionstart
160}
161
162#[derive(Debug, Clone, ImplicitClone, Default)]
164pub enum Listeners {
165 #[default]
168 None,
169
170 Pending(Box<[Option<Rc<dyn Listener>>]>),
172}
173
174impl PartialEq for Listeners {
175 fn eq(&self, rhs: &Self) -> bool {
176 use Listeners::*;
177
178 match (self, rhs) {
179 (None, None) => true,
180 (Pending(lhs), Pending(rhs)) => {
181 if lhs.len() != rhs.len() {
182 false
183 } else {
184 use std::option::Option::None;
185
186 lhs.iter()
187 .zip(rhs.iter())
188 .all(|(lhs, rhs)| match (lhs, rhs) {
189 (Some(lhs), Some(rhs)) => {
190 #[allow(ambiguous_wide_pointer_comparisons)]
194 Rc::ptr_eq(lhs, rhs)
195 }
196 (None, None) => true,
197 _ => false,
198 })
199 }
200 }
201 (None, Pending(pending)) | (Pending(pending), None) => pending.is_empty(),
202 }
203 }
204}