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)]
164pub enum Listeners {
165 None,
168
169 Pending(Box<[Option<Rc<dyn Listener>>]>),
171}
172
173impl ImplicitClone for Listeners {}
174
175impl PartialEq for Listeners {
176 fn eq(&self, rhs: &Self) -> bool {
177 use Listeners::*;
178
179 match (self, rhs) {
180 (None, None) => true,
181 (Pending(lhs), Pending(rhs)) => {
182 if lhs.len() != rhs.len() {
183 false
184 } else {
185 use std::option::Option::None;
186
187 lhs.iter()
188 .zip(rhs.iter())
189 .all(|(lhs, rhs)| match (lhs, rhs) {
190 (Some(lhs), Some(rhs)) => {
191 #[allow(ambiguous_wide_pointer_comparisons)]
195 Rc::ptr_eq(lhs, rhs)
196 }
197 (None, None) => true,
198 _ => false,
199 })
200 }
201 }
202 (None, Pending(pending)) | (Pending(pending), None) => pending.is_empty(),
203 }
204 }
205}
206
207impl Clone for Listeners {
208 fn clone(&self) -> Self {
209 match self {
210 Self::None => Self::None,
211 Self::Pending(v) => Self::Pending(v.clone()),
212 }
213 }
214}
215
216impl Default for Listeners {
217 fn default() -> Self {
218 Self::None
219 }
220}