1use crate::{
2 build_action_from_type, Action, Bounds, DispatchPhase, Element, FocusEvent, FocusHandle,
3 FocusId, KeyBinding, KeyContext, KeyMatch, Keymap, Keystroke, KeystrokeMatcher, MouseDownEvent,
4 Pixels, 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 bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
149 self.keymap
150 .lock()
151 .bindings_for_action(action.type_id())
152 .filter(|candidate| candidate.action.partial_eq(action))
153 .cloned()
154 .collect()
155 }
156
157 pub fn dispatch_key(
158 &mut self,
159 keystroke: &Keystroke,
160 context: &[KeyContext],
161 ) -> Option<Box<dyn Action>> {
162 if !self.keystroke_matchers.contains_key(context) {
163 let keystroke_contexts = context.iter().cloned().collect();
164 self.keystroke_matchers.insert(
165 keystroke_contexts,
166 KeystrokeMatcher::new(self.keymap.clone()),
167 );
168 }
169
170 let keystroke_matcher = self.keystroke_matchers.get_mut(context).unwrap();
171 if let KeyMatch::Some(action) = keystroke_matcher.match_keystroke(keystroke, context) {
172 // Clear all pending keystrokes when an action has been found.
173 for keystroke_matcher in self.keystroke_matchers.values_mut() {
174 keystroke_matcher.clear_pending();
175 }
176
177 Some(action)
178 } else {
179 None
180 }
181 }
182
183 pub fn dispatch_path(&self, target: DispatchNodeId) -> SmallVec<[DispatchNodeId; 32]> {
184 let mut dispatch_path: SmallVec<[DispatchNodeId; 32]> = SmallVec::new();
185 let mut current_node_id = Some(target);
186 while let Some(node_id) = current_node_id {
187 dispatch_path.push(node_id);
188 current_node_id = self.nodes[node_id.0].parent;
189 }
190 dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node.
191 dispatch_path
192 }
193
194 pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode {
195 &self.nodes[node_id.0]
196 }
197
198 fn active_node(&mut self) -> &mut DispatchNode {
199 let active_node_id = self.active_node_id();
200 &mut self.nodes[active_node_id.0]
201 }
202
203 pub fn focusable_node_id(&self, target: FocusId) -> Option<DispatchNodeId> {
204 self.focusable_node_ids.get(&target).copied()
205 }
206
207 fn active_node_id(&self) -> DispatchNodeId {
208 *self.node_stack.last().unwrap()
209 }
210}
211
212pub trait KeyDispatch<V: 'static>: 'static {
213 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>>;
214 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>>;
215 fn key_context(&self) -> &KeyContext;
216 fn key_context_mut(&mut self) -> &mut KeyContext;
217
218 fn initialize<R>(
219 &mut self,
220 focus_handle: Option<FocusHandle>,
221 cx: &mut ViewContext<V>,
222 f: impl FnOnce(Option<FocusHandle>, &mut ViewContext<V>) -> R,
223 ) -> R {
224 let focus_handle = if let Some(focusable) = self.as_focusable_mut() {
225 let focus_handle = focusable
226 .focus_handle
227 .get_or_insert_with(|| focus_handle.unwrap_or_else(|| cx.focus_handle()))
228 .clone();
229 for listener in focusable.focus_listeners.drain(..) {
230 let focus_handle = focus_handle.clone();
231 cx.on_focus_changed(move |view, event, cx| {
232 listener(view, &focus_handle, event, cx)
233 });
234 }
235 Some(focus_handle)
236 } else {
237 None
238 };
239
240 cx.with_key_dispatch(self.key_context().clone(), focus_handle, f)
241 }
242
243 fn refine_style(&self, style: &mut Style, cx: &WindowContext) {
244 if let Some(focusable) = self.as_focusable() {
245 let focus_handle = focusable
246 .focus_handle
247 .as_ref()
248 .expect("must call initialize before refine_style");
249 if focus_handle.contains_focused(cx) {
250 style.refine(&focusable.focus_in_style);
251 }
252
253 if focus_handle.within_focused(cx) {
254 style.refine(&focusable.in_focus_style);
255 }
256
257 if focus_handle.is_focused(cx) {
258 style.refine(&focusable.focus_style);
259 }
260 }
261 }
262
263 fn paint(&self, bounds: Bounds<Pixels>, cx: &mut WindowContext) {
264 if let Some(focusable) = self.as_focusable() {
265 let focus_handle = focusable
266 .focus_handle
267 .clone()
268 .expect("must call initialize before paint");
269 cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
270 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
271 if !cx.default_prevented() {
272 cx.focus(&focus_handle);
273 cx.prevent_default();
274 }
275 }
276 })
277 }
278 }
279}
280
281pub struct FocusableKeyDispatch<V> {
282 pub non_focusable: NonFocusableKeyDispatch,
283 pub focus_handle: Option<FocusHandle>,
284 pub focus_listeners: FocusListeners<V>,
285 pub focus_style: StyleRefinement,
286 pub focus_in_style: StyleRefinement,
287 pub in_focus_style: StyleRefinement,
288}
289
290impl<V> FocusableKeyDispatch<V> {
291 pub fn new(non_focusable: NonFocusableKeyDispatch) -> Self {
292 Self {
293 non_focusable,
294 focus_handle: None,
295 focus_listeners: FocusListeners::default(),
296 focus_style: StyleRefinement::default(),
297 focus_in_style: StyleRefinement::default(),
298 in_focus_style: StyleRefinement::default(),
299 }
300 }
301
302 pub fn tracked(non_focusable: NonFocusableKeyDispatch, handle: &FocusHandle) -> Self {
303 Self {
304 non_focusable,
305 focus_handle: Some(handle.clone()),
306 focus_listeners: FocusListeners::default(),
307 focus_style: StyleRefinement::default(),
308 focus_in_style: StyleRefinement::default(),
309 in_focus_style: StyleRefinement::default(),
310 }
311 }
312}
313
314impl<V: 'static> KeyDispatch<V> for FocusableKeyDispatch<V> {
315 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>> {
316 Some(self)
317 }
318
319 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>> {
320 Some(self)
321 }
322
323 fn key_context(&self) -> &KeyContext {
324 &self.non_focusable.key_context
325 }
326
327 fn key_context_mut(&mut self) -> &mut KeyContext {
328 &mut self.non_focusable.key_context
329 }
330}
331
332#[derive(Default)]
333pub struct NonFocusableKeyDispatch {
334 pub(crate) key_context: KeyContext,
335}
336
337impl<V: 'static> KeyDispatch<V> for NonFocusableKeyDispatch {
338 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>> {
339 None
340 }
341
342 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>> {
343 None
344 }
345
346 fn key_context(&self) -> &KeyContext {
347 &self.key_context
348 }
349
350 fn key_context_mut(&mut self) -> &mut KeyContext {
351 &mut self.key_context
352 }
353}
354
355pub trait Focusable<V: 'static>: Element<V> {
356 fn focus_listeners(&mut self) -> &mut FocusListeners<V>;
357 fn set_focus_style(&mut self, style: StyleRefinement);
358 fn set_focus_in_style(&mut self, style: StyleRefinement);
359 fn set_in_focus_style(&mut self, style: StyleRefinement);
360
361 fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
362 where
363 Self: Sized,
364 {
365 self.set_focus_style(f(StyleRefinement::default()));
366 self
367 }
368
369 fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
370 where
371 Self: Sized,
372 {
373 self.set_focus_in_style(f(StyleRefinement::default()));
374 self
375 }
376
377 fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
378 where
379 Self: Sized,
380 {
381 self.set_in_focus_style(f(StyleRefinement::default()));
382 self
383 }
384
385 fn on_focus(
386 mut self,
387 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
388 ) -> Self
389 where
390 Self: Sized,
391 {
392 self.focus_listeners()
393 .push(Box::new(move |view, focus_handle, event, cx| {
394 if event.focused.as_ref() == Some(focus_handle) {
395 listener(view, event, cx)
396 }
397 }));
398 self
399 }
400
401 fn on_blur(
402 mut self,
403 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
404 ) -> Self
405 where
406 Self: Sized,
407 {
408 self.focus_listeners()
409 .push(Box::new(move |view, focus_handle, event, cx| {
410 if event.blurred.as_ref() == Some(focus_handle) {
411 listener(view, event, cx)
412 }
413 }));
414 self
415 }
416
417 fn on_focus_in(
418 mut self,
419 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
420 ) -> Self
421 where
422 Self: Sized,
423 {
424 self.focus_listeners()
425 .push(Box::new(move |view, focus_handle, event, cx| {
426 let descendant_blurred = event
427 .blurred
428 .as_ref()
429 .map_or(false, |blurred| focus_handle.contains(blurred, cx));
430 let descendant_focused = event
431 .focused
432 .as_ref()
433 .map_or(false, |focused| focus_handle.contains(focused, cx));
434
435 if !descendant_blurred && descendant_focused {
436 listener(view, event, cx)
437 }
438 }));
439 self
440 }
441
442 fn on_focus_out(
443 mut self,
444 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
445 ) -> Self
446 where
447 Self: Sized,
448 {
449 self.focus_listeners()
450 .push(Box::new(move |view, focus_handle, event, cx| {
451 let descendant_blurred = event
452 .blurred
453 .as_ref()
454 .map_or(false, |blurred| focus_handle.contains(blurred, cx));
455 let descendant_focused = event
456 .focused
457 .as_ref()
458 .map_or(false, |focused| focus_handle.contains(focused, cx));
459 if descendant_blurred && !descendant_focused {
460 listener(view, event, cx)
461 }
462 }));
463 self
464 }
465}