1use crate::{Element, FocusEvent, FocusHandle, StyleRefinement, ViewContext};
2use smallvec::SmallVec;
3use std::sync::Arc;
4
5pub type FocusListeners<V> = SmallVec<[FocusListener<V>; 2]>;
6
7pub type FocusListener<V> =
8 Arc<dyn Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + Send + Sync + 'static>;
9
10pub trait Focus: Element {
11 fn focus_listeners(&mut self) -> &mut FocusListeners<Self::ViewState>;
12 fn set_focus_style(&mut self, style: StyleRefinement);
13 fn set_focus_in_style(&mut self, style: StyleRefinement);
14 fn set_in_focus_style(&mut self, style: StyleRefinement);
15 fn handle(&self) -> &FocusHandle;
16
17 fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
18 where
19 Self: Sized,
20 {
21 self.set_focus_style(f(StyleRefinement::default()));
22 self
23 }
24
25 fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
26 where
27 Self: Sized,
28 {
29 self.set_focus_in_style(f(StyleRefinement::default()));
30 self
31 }
32
33 fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
34 where
35 Self: Sized,
36 {
37 self.set_in_focus_style(f(StyleRefinement::default()));
38 self
39 }
40
41 fn on_focus(
42 mut self,
43 listener: impl Fn(&mut Self::ViewState, &FocusEvent, &mut ViewContext<Self::ViewState>)
44 + Send
45 + Sync
46 + 'static,
47 ) -> Self
48 where
49 Self: Sized,
50 {
51 let handle = self.handle().clone();
52 self.focus_listeners()
53 .push(Arc::new(move |view, event, cx| {
54 if event.focused.as_ref() == Some(&handle) {
55 listener(view, event, cx)
56 }
57 }));
58 self
59 }
60
61 fn on_blur(
62 mut self,
63 listener: impl Fn(&mut Self::ViewState, &FocusEvent, &mut ViewContext<Self::ViewState>)
64 + Send
65 + Sync
66 + 'static,
67 ) -> Self
68 where
69 Self: Sized,
70 {
71 let handle = self.handle().clone();
72 self.focus_listeners()
73 .push(Arc::new(move |view, event, cx| {
74 if event.blurred.as_ref() == Some(&handle) {
75 listener(view, event, cx)
76 }
77 }));
78 self
79 }
80
81 fn on_focus_in(
82 mut self,
83 listener: impl Fn(&mut Self::ViewState, &FocusEvent, &mut ViewContext<Self::ViewState>)
84 + Send
85 + Sync
86 + 'static,
87 ) -> Self
88 where
89 Self: Sized,
90 {
91 let handle = self.handle().clone();
92 self.focus_listeners()
93 .push(Arc::new(move |view, event, cx| {
94 let descendant_blurred = event
95 .blurred
96 .as_ref()
97 .map_or(false, |blurred| handle.contains(blurred, cx));
98 let descendant_focused = event
99 .focused
100 .as_ref()
101 .map_or(false, |focused| handle.contains(focused, cx));
102
103 if !descendant_blurred && descendant_focused {
104 listener(view, event, cx)
105 }
106 }));
107 self
108 }
109
110 fn on_focus_out(
111 mut self,
112 listener: impl Fn(&mut Self::ViewState, &FocusEvent, &mut ViewContext<Self::ViewState>)
113 + Send
114 + Sync
115 + 'static,
116 ) -> Self
117 where
118 Self: Sized,
119 {
120 let handle = self.handle().clone();
121 self.focus_listeners()
122 .push(Arc::new(move |view, event, cx| {
123 let descendant_blurred = event
124 .blurred
125 .as_ref()
126 .map_or(false, |blurred| handle.contains(blurred, cx));
127 let descendant_focused = event
128 .focused
129 .as_ref()
130 .map_or(false, |focused| handle.contains(focused, cx));
131 if descendant_blurred && !descendant_focused {
132 listener(view, event, cx)
133 }
134 }));
135 self
136 }
137}