1use crate::{
2 build_action_from_type, Action, Bounds, DispatchPhase, Element, FocusEvent, FocusHandle,
3 FocusId, KeyContext, KeyMatch, Keymap, Keystroke, KeystrokeMatcher, MouseDownEvent, Pixels,
4 Style, StyleRefinement, ViewContext, WindowContext,
5};
6use collections::HashMap;
7use parking_lot::Mutex;
8use refineable::Refineable;
9use smallvec::SmallVec;
10use std::{
11 any::{Any, TypeId},
12 rc::Rc,
13 sync::Arc,
14};
15use util::ResultExt;
16
17pub type FocusListeners<V> = SmallVec<[FocusListener<V>; 2]>;
18pub type FocusListener<V> =
19 Box<dyn Fn(&mut V, &FocusHandle, &FocusEvent, &mut ViewContext<V>) + 'static>;
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
22pub struct DispatchNodeId(usize);
23
24pub(crate) struct DispatchTree {
25 node_stack: Vec<DispatchNodeId>,
26 context_stack: Vec<KeyContext>,
27 nodes: Vec<DispatchNode>,
28 focusable_node_ids: HashMap<FocusId, DispatchNodeId>,
29 keystroke_matchers: HashMap<SmallVec<[KeyContext; 4]>, KeystrokeMatcher>,
30 keymap: Arc<Mutex<Keymap>>,
31}
32
33#[derive(Default)]
34pub(crate) struct DispatchNode {
35 pub key_listeners: SmallVec<[KeyListener; 2]>,
36 pub action_listeners: SmallVec<[DispatchActionListener; 16]>,
37 pub context: KeyContext,
38 parent: Option<DispatchNodeId>,
39}
40
41type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>;
42
43#[derive(Clone)]
44pub(crate) struct DispatchActionListener {
45 pub(crate) action_type: TypeId,
46 pub(crate) listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
47}
48
49impl DispatchTree {
50 pub fn new(keymap: Arc<Mutex<Keymap>>) -> Self {
51 Self {
52 node_stack: Vec::new(),
53 context_stack: Vec::new(),
54 nodes: Vec::new(),
55 focusable_node_ids: HashMap::default(),
56 keystroke_matchers: HashMap::default(),
57 keymap,
58 }
59 }
60
61 pub fn clear(&mut self) {
62 self.node_stack.clear();
63 self.nodes.clear();
64 self.context_stack.clear();
65 self.focusable_node_ids.clear();
66 self.keystroke_matchers.clear();
67 }
68
69 pub fn push_node(&mut self, context: KeyContext, old_dispatcher: &mut Self) {
70 let parent = self.node_stack.last().copied();
71 let node_id = DispatchNodeId(self.nodes.len());
72 self.nodes.push(DispatchNode {
73 parent,
74 ..Default::default()
75 });
76 self.node_stack.push(node_id);
77 if !context.is_empty() {
78 self.active_node().context = context.clone();
79 self.context_stack.push(context);
80 if let Some((context_stack, matcher)) = old_dispatcher
81 .keystroke_matchers
82 .remove_entry(self.context_stack.as_slice())
83 {
84 self.keystroke_matchers.insert(context_stack, matcher);
85 }
86 }
87 }
88
89 pub fn pop_node(&mut self) {
90 let node_id = self.node_stack.pop().unwrap();
91 if !self.nodes[node_id.0].context.is_empty() {
92 self.context_stack.pop();
93 }
94 }
95
96 pub fn on_key_event(&mut self, listener: KeyListener) {
97 self.active_node().key_listeners.push(listener);
98 }
99
100 pub fn on_action(
101 &mut self,
102 action_type: TypeId,
103 listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
104 ) {
105 self.active_node()
106 .action_listeners
107 .push(DispatchActionListener {
108 action_type,
109 listener,
110 });
111 }
112
113 pub fn make_focusable(&mut self, focus_id: FocusId) {
114 self.focusable_node_ids
115 .insert(focus_id, self.active_node_id());
116 }
117
118 pub fn focus_contains(&self, parent: FocusId, child: FocusId) -> bool {
119 if parent == child {
120 return true;
121 }
122
123 if let Some(parent_node_id) = self.focusable_node_ids.get(&parent) {
124 let mut current_node_id = self.focusable_node_ids.get(&child).copied();
125 while let Some(node_id) = current_node_id {
126 if node_id == *parent_node_id {
127 return true;
128 }
129 current_node_id = self.nodes[node_id.0].parent;
130 }
131 }
132 false
133 }
134
135 pub fn available_actions(&self, target: FocusId) -> Vec<Box<dyn Action>> {
136 let mut actions = Vec::new();
137 if let Some(node) = self.focusable_node_ids.get(&target) {
138 for node_id in self.dispatch_path(*node) {
139 let node = &self.nodes[node_id.0];
140 for DispatchActionListener { action_type, .. } in &node.action_listeners {
141 actions.extend(build_action_from_type(action_type).log_err());
142 }
143 }
144 }
145 actions
146 }
147
148 pub fn dispatch_key(
149 &mut self,
150 keystroke: &Keystroke,
151 context: &[KeyContext],
152 ) -> Option<Box<dyn Action>> {
153 if !self.keystroke_matchers.contains_key(context) {
154 let keystroke_contexts = context.iter().cloned().collect();
155 self.keystroke_matchers.insert(
156 keystroke_contexts,
157 KeystrokeMatcher::new(self.keymap.clone()),
158 );
159 }
160
161 let keystroke_matcher = self.keystroke_matchers.get_mut(context).unwrap();
162 if let KeyMatch::Some(action) = keystroke_matcher.match_keystroke(keystroke, context) {
163 // Clear all pending keystrokes when an action has been found.
164 for keystroke_matcher in self.keystroke_matchers.values_mut() {
165 keystroke_matcher.clear_pending();
166 }
167
168 Some(action)
169 } else {
170 None
171 }
172 }
173
174 pub fn dispatch_path(&self, target: DispatchNodeId) -> SmallVec<[DispatchNodeId; 32]> {
175 let mut dispatch_path: SmallVec<[DispatchNodeId; 32]> = SmallVec::new();
176 let mut current_node_id = Some(target);
177 while let Some(node_id) = current_node_id {
178 dispatch_path.push(node_id);
179 current_node_id = self.nodes[node_id.0].parent;
180 }
181 dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node.
182 dispatch_path
183 }
184
185 pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode {
186 &self.nodes[node_id.0]
187 }
188
189 fn active_node(&mut self) -> &mut DispatchNode {
190 let active_node_id = self.active_node_id();
191 &mut self.nodes[active_node_id.0]
192 }
193
194 pub fn focusable_node_id(&self, target: FocusId) -> Option<DispatchNodeId> {
195 self.focusable_node_ids.get(&target).copied()
196 }
197
198 fn active_node_id(&self) -> DispatchNodeId {
199 *self.node_stack.last().unwrap()
200 }
201}
202
203pub trait KeyDispatch<V: 'static>: 'static {
204 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>>;
205 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>>;
206 fn key_context(&self) -> &KeyContext;
207 fn key_context_mut(&mut self) -> &mut KeyContext;
208
209 fn initialize<R>(
210 &mut self,
211 focus_handle: Option<FocusHandle>,
212 cx: &mut ViewContext<V>,
213 f: impl FnOnce(Option<FocusHandle>, &mut ViewContext<V>) -> R,
214 ) -> R {
215 let focus_handle = if let Some(focusable) = self.as_focusable_mut() {
216 let focus_handle = focusable
217 .focus_handle
218 .get_or_insert_with(|| focus_handle.unwrap_or_else(|| cx.focus_handle()))
219 .clone();
220 for listener in focusable.focus_listeners.drain(..) {
221 let focus_handle = focus_handle.clone();
222 cx.on_focus_changed(move |view, event, cx| {
223 listener(view, &focus_handle, event, cx)
224 });
225 }
226 Some(focus_handle)
227 } else {
228 None
229 };
230
231 cx.with_key_dispatch(self.key_context().clone(), focus_handle, f)
232 }
233
234 fn refine_style(&self, style: &mut Style, cx: &WindowContext) {
235 if let Some(focusable) = self.as_focusable() {
236 let focus_handle = focusable
237 .focus_handle
238 .as_ref()
239 .expect("must call initialize before refine_style");
240 if focus_handle.contains_focused(cx) {
241 style.refine(&focusable.focus_in_style);
242 }
243
244 if focus_handle.within_focused(cx) {
245 style.refine(&focusable.in_focus_style);
246 }
247
248 if focus_handle.is_focused(cx) {
249 style.refine(&focusable.focus_style);
250 }
251 }
252 }
253
254 fn paint(&self, bounds: Bounds<Pixels>, cx: &mut WindowContext) {
255 if let Some(focusable) = self.as_focusable() {
256 let focus_handle = focusable
257 .focus_handle
258 .clone()
259 .expect("must call initialize before paint");
260 cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
261 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
262 if !cx.default_prevented() {
263 cx.focus(&focus_handle);
264 cx.prevent_default();
265 }
266 }
267 })
268 }
269 }
270}
271
272pub struct FocusableKeyDispatch<V> {
273 pub non_focusable: NonFocusableKeyDispatch,
274 pub focus_handle: Option<FocusHandle>,
275 pub focus_listeners: FocusListeners<V>,
276 pub focus_style: StyleRefinement,
277 pub focus_in_style: StyleRefinement,
278 pub in_focus_style: StyleRefinement,
279}
280
281impl<V> FocusableKeyDispatch<V> {
282 pub fn new(non_focusable: NonFocusableKeyDispatch) -> Self {
283 Self {
284 non_focusable,
285 focus_handle: None,
286 focus_listeners: FocusListeners::default(),
287 focus_style: StyleRefinement::default(),
288 focus_in_style: StyleRefinement::default(),
289 in_focus_style: StyleRefinement::default(),
290 }
291 }
292
293 pub fn tracked(non_focusable: NonFocusableKeyDispatch, handle: &FocusHandle) -> Self {
294 Self {
295 non_focusable,
296 focus_handle: Some(handle.clone()),
297 focus_listeners: FocusListeners::default(),
298 focus_style: StyleRefinement::default(),
299 focus_in_style: StyleRefinement::default(),
300 in_focus_style: StyleRefinement::default(),
301 }
302 }
303}
304
305impl<V: 'static> KeyDispatch<V> for FocusableKeyDispatch<V> {
306 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>> {
307 Some(self)
308 }
309
310 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>> {
311 Some(self)
312 }
313
314 fn key_context(&self) -> &KeyContext {
315 &self.non_focusable.key_context
316 }
317
318 fn key_context_mut(&mut self) -> &mut KeyContext {
319 &mut self.non_focusable.key_context
320 }
321}
322
323#[derive(Default)]
324pub struct NonFocusableKeyDispatch {
325 pub(crate) key_context: KeyContext,
326}
327
328impl<V: 'static> KeyDispatch<V> for NonFocusableKeyDispatch {
329 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>> {
330 None
331 }
332
333 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>> {
334 None
335 }
336
337 fn key_context(&self) -> &KeyContext {
338 &self.key_context
339 }
340
341 fn key_context_mut(&mut self) -> &mut KeyContext {
342 &mut self.key_context
343 }
344}
345
346pub trait Focusable<V: 'static>: Element<V> {
347 fn focus_listeners(&mut self) -> &mut FocusListeners<V>;
348 fn set_focus_style(&mut self, style: StyleRefinement);
349 fn set_focus_in_style(&mut self, style: StyleRefinement);
350 fn set_in_focus_style(&mut self, style: StyleRefinement);
351
352 fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
353 where
354 Self: Sized,
355 {
356 self.set_focus_style(f(StyleRefinement::default()));
357 self
358 }
359
360 fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
361 where
362 Self: Sized,
363 {
364 self.set_focus_in_style(f(StyleRefinement::default()));
365 self
366 }
367
368 fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
369 where
370 Self: Sized,
371 {
372 self.set_in_focus_style(f(StyleRefinement::default()));
373 self
374 }
375
376 fn on_focus(
377 mut self,
378 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
379 ) -> Self
380 where
381 Self: Sized,
382 {
383 self.focus_listeners()
384 .push(Box::new(move |view, focus_handle, event, cx| {
385 if event.focused.as_ref() == Some(focus_handle) {
386 listener(view, event, cx)
387 }
388 }));
389 self
390 }
391
392 fn on_blur(
393 mut self,
394 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
395 ) -> Self
396 where
397 Self: Sized,
398 {
399 self.focus_listeners()
400 .push(Box::new(move |view, focus_handle, event, cx| {
401 if event.blurred.as_ref() == Some(focus_handle) {
402 listener(view, event, cx)
403 }
404 }));
405 self
406 }
407
408 fn on_focus_in(
409 mut self,
410 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
411 ) -> Self
412 where
413 Self: Sized,
414 {
415 self.focus_listeners()
416 .push(Box::new(move |view, focus_handle, event, cx| {
417 let descendant_blurred = event
418 .blurred
419 .as_ref()
420 .map_or(false, |blurred| focus_handle.contains(blurred, cx));
421 let descendant_focused = event
422 .focused
423 .as_ref()
424 .map_or(false, |focused| focus_handle.contains(focused, cx));
425
426 if !descendant_blurred && descendant_focused {
427 listener(view, event, cx)
428 }
429 }));
430 self
431 }
432
433 fn on_focus_out(
434 mut self,
435 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
436 ) -> Self
437 where
438 Self: Sized,
439 {
440 self.focus_listeners()
441 .push(Box::new(move |view, focus_handle, event, cx| {
442 let descendant_blurred = event
443 .blurred
444 .as_ref()
445 .map_or(false, |blurred| focus_handle.contains(blurred, cx));
446 let descendant_focused = event
447 .focused
448 .as_ref()
449 .map_or(false, |focused| focus_handle.contains(focused, cx));
450 if descendant_blurred && !descendant_focused {
451 listener(view, event, cx)
452 }
453 }));
454 self
455 }
456}