1use crate::{
2 Action, ActionRegistry, DispatchPhase, EntityId, FocusId, KeyBinding, KeyContext, KeyMatch,
3 Keymap, Keystroke, KeystrokeMatcher, WindowContext,
4};
5use collections::FxHashMap;
6use parking_lot::Mutex;
7use smallvec::{smallvec, SmallVec};
8use std::{
9 any::{Any, TypeId},
10 mem,
11 rc::Rc,
12 sync::Arc,
13};
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
16pub struct DispatchNodeId(usize);
17
18pub(crate) struct DispatchTree {
19 node_stack: Vec<DispatchNodeId>,
20 pub(crate) context_stack: Vec<KeyContext>,
21 view_stack: Vec<EntityId>,
22 nodes: Vec<DispatchNode>,
23 focusable_node_ids: FxHashMap<FocusId, DispatchNodeId>,
24 view_node_ids: FxHashMap<EntityId, DispatchNodeId>,
25 keystroke_matchers: FxHashMap<SmallVec<[KeyContext; 4]>, KeystrokeMatcher>,
26 keymap: Arc<Mutex<Keymap>>,
27 action_registry: Rc<ActionRegistry>,
28}
29
30#[derive(Default)]
31pub(crate) struct DispatchNode {
32 pub key_listeners: Vec<KeyListener>,
33 pub action_listeners: Vec<DispatchActionListener>,
34 pub context: Option<KeyContext>,
35 focus_id: Option<FocusId>,
36 view_id: Option<EntityId>,
37 parent: Option<DispatchNodeId>,
38}
39
40type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>;
41
42#[derive(Clone)]
43pub(crate) struct DispatchActionListener {
44 pub(crate) action_type: TypeId,
45 pub(crate) listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
46}
47
48impl DispatchTree {
49 pub fn new(keymap: Arc<Mutex<Keymap>>, action_registry: Rc<ActionRegistry>) -> Self {
50 Self {
51 node_stack: Vec::new(),
52 context_stack: Vec::new(),
53 view_stack: Vec::new(),
54 nodes: Vec::new(),
55 focusable_node_ids: FxHashMap::default(),
56 view_node_ids: FxHashMap::default(),
57 keystroke_matchers: FxHashMap::default(),
58 keymap,
59 action_registry,
60 }
61 }
62
63 pub fn clear(&mut self) {
64 self.node_stack.clear();
65 self.context_stack.clear();
66 self.view_stack.clear();
67 self.nodes.clear();
68 self.focusable_node_ids.clear();
69 self.view_node_ids.clear();
70 self.keystroke_matchers.clear();
71 }
72
73 pub fn push_node(
74 &mut self,
75 context: Option<KeyContext>,
76 focus_id: Option<FocusId>,
77 view_id: Option<EntityId>,
78 ) {
79 let parent = self.node_stack.last().copied();
80 let node_id = DispatchNodeId(self.nodes.len());
81 self.nodes.push(DispatchNode {
82 parent,
83 focus_id,
84 view_id,
85 ..Default::default()
86 });
87 self.node_stack.push(node_id);
88
89 if let Some(context) = context {
90 self.active_node().context = Some(context.clone());
91 self.context_stack.push(context);
92 }
93
94 if let Some(focus_id) = focus_id {
95 self.focusable_node_ids.insert(focus_id, node_id);
96 }
97
98 if let Some(view_id) = view_id {
99 self.view_stack.push(view_id);
100 self.view_node_ids.insert(view_id, node_id);
101 }
102 }
103
104 pub fn pop_node(&mut self) {
105 let node = &self.nodes[self.active_node_id().0];
106 if node.context.is_some() {
107 self.context_stack.pop();
108 }
109 if node.view_id.is_some() {
110 self.view_stack.pop();
111 }
112 self.node_stack.pop();
113 }
114
115 fn move_node(&mut self, source_node: &mut DispatchNode) {
116 self.push_node(
117 source_node.context.take(),
118 source_node.focus_id,
119 source_node.view_id,
120 );
121 let target_node = self.active_node();
122 target_node.key_listeners = mem::take(&mut source_node.key_listeners);
123 target_node.action_listeners = mem::take(&mut source_node.action_listeners);
124 }
125
126 pub fn graft(&mut self, view_id: EntityId, source: &mut Self) -> SmallVec<[EntityId; 8]> {
127 let view_source_node_id = source
128 .view_node_ids
129 .get(&view_id)
130 .expect("view should exist in previous dispatch tree");
131 let view_source_node = &mut source.nodes[view_source_node_id.0];
132 self.move_node(view_source_node);
133
134 let mut grafted_view_ids = smallvec![view_id];
135 let mut source_stack = vec![*view_source_node_id];
136 for (source_node_id, source_node) in source
137 .nodes
138 .iter_mut()
139 .enumerate()
140 .skip(view_source_node_id.0 + 1)
141 {
142 let source_node_id = DispatchNodeId(source_node_id);
143 while let Some(source_ancestor) = source_stack.last() {
144 if source_node.parent != Some(*source_ancestor) {
145 source_stack.pop();
146 self.pop_node();
147 }
148 }
149
150 if source_stack.is_empty() {
151 break;
152 } else {
153 source_stack.push(source_node_id);
154 self.move_node(source_node);
155 if let Some(view_id) = source_node.view_id {
156 grafted_view_ids.push(view_id);
157 }
158 }
159 }
160
161 while !source_stack.is_empty() {
162 self.pop_node();
163 }
164
165 grafted_view_ids
166 }
167
168 pub fn clear_pending_keystrokes(&mut self) {
169 self.keystroke_matchers.clear();
170 }
171
172 /// Preserve keystroke matchers from previous frames to support multi-stroke
173 /// bindings across multiple frames.
174 pub fn preserve_pending_keystrokes(&mut self, old_tree: &mut Self, focus_id: Option<FocusId>) {
175 if let Some(node_id) = focus_id.and_then(|focus_id| self.focusable_node_id(focus_id)) {
176 let dispatch_path = self.dispatch_path(node_id);
177
178 self.context_stack.clear();
179 for node_id in dispatch_path {
180 let node = self.node(node_id);
181 if let Some(context) = node.context.clone() {
182 self.context_stack.push(context);
183 }
184
185 if let Some((context_stack, matcher)) = old_tree
186 .keystroke_matchers
187 .remove_entry(self.context_stack.as_slice())
188 {
189 self.keystroke_matchers.insert(context_stack, matcher);
190 }
191 }
192 }
193 }
194
195 pub fn on_key_event(&mut self, listener: KeyListener) {
196 self.active_node().key_listeners.push(listener);
197 }
198
199 pub fn on_action(
200 &mut self,
201 action_type: TypeId,
202 listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
203 ) {
204 self.active_node()
205 .action_listeners
206 .push(DispatchActionListener {
207 action_type,
208 listener,
209 });
210 }
211
212 pub fn focus_contains(&self, parent: FocusId, child: FocusId) -> bool {
213 if parent == child {
214 return true;
215 }
216
217 if let Some(parent_node_id) = self.focusable_node_ids.get(&parent) {
218 let mut current_node_id = self.focusable_node_ids.get(&child).copied();
219 while let Some(node_id) = current_node_id {
220 if node_id == *parent_node_id {
221 return true;
222 }
223 current_node_id = self.nodes[node_id.0].parent;
224 }
225 }
226 false
227 }
228
229 pub fn available_actions(&self, target: DispatchNodeId) -> Vec<Box<dyn Action>> {
230 let mut actions = Vec::<Box<dyn Action>>::new();
231 for node_id in self.dispatch_path(target) {
232 let node = &self.nodes[node_id.0];
233 for DispatchActionListener { action_type, .. } in &node.action_listeners {
234 if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id())
235 {
236 // Intentionally silence these errors without logging.
237 // If an action cannot be built by default, it's not available.
238 let action = self.action_registry.build_action_type(action_type).ok();
239 if let Some(action) = action {
240 actions.insert(ix, action);
241 }
242 }
243 }
244 }
245 actions
246 }
247
248 pub fn is_action_available(&self, action: &dyn Action, target: DispatchNodeId) -> bool {
249 for node_id in self.dispatch_path(target) {
250 let node = &self.nodes[node_id.0];
251 if node
252 .action_listeners
253 .iter()
254 .any(|listener| listener.action_type == action.as_any().type_id())
255 {
256 return true;
257 }
258 }
259 false
260 }
261
262 pub fn bindings_for_action(
263 &self,
264 action: &dyn Action,
265 context_stack: &Vec<KeyContext>,
266 ) -> Vec<KeyBinding> {
267 let keymap = self.keymap.lock();
268 keymap
269 .bindings_for_action(action)
270 .filter(|binding| {
271 for i in 1..context_stack.len() {
272 let context = &context_stack[0..i];
273 if keymap.binding_enabled(binding, context) {
274 return true;
275 }
276 }
277 false
278 })
279 .cloned()
280 .collect()
281 }
282
283 pub fn dispatch_key(
284 &mut self,
285 keystroke: &Keystroke,
286 context: &[KeyContext],
287 ) -> Vec<Box<dyn Action>> {
288 if !self.keystroke_matchers.contains_key(context) {
289 let keystroke_contexts = context.iter().cloned().collect();
290 self.keystroke_matchers.insert(
291 keystroke_contexts,
292 KeystrokeMatcher::new(self.keymap.clone()),
293 );
294 }
295
296 let keystroke_matcher = self.keystroke_matchers.get_mut(context).unwrap();
297 if let KeyMatch::Some(actions) = keystroke_matcher.match_keystroke(keystroke, context) {
298 // Clear all pending keystrokes when an action has been found.
299 for keystroke_matcher in self.keystroke_matchers.values_mut() {
300 keystroke_matcher.clear_pending();
301 }
302
303 actions
304 } else {
305 vec![]
306 }
307 }
308
309 pub fn has_pending_keystrokes(&self) -> bool {
310 self.keystroke_matchers
311 .iter()
312 .any(|(_, matcher)| matcher.has_pending_keystrokes())
313 }
314
315 pub fn dispatch_path(&self, target: DispatchNodeId) -> SmallVec<[DispatchNodeId; 32]> {
316 let mut dispatch_path: SmallVec<[DispatchNodeId; 32]> = SmallVec::new();
317 let mut current_node_id = Some(target);
318 while let Some(node_id) = current_node_id {
319 dispatch_path.push(node_id);
320 current_node_id = self.nodes[node_id.0].parent;
321 }
322 dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node.
323 dispatch_path
324 }
325
326 pub fn focus_path(&self, focus_id: FocusId) -> SmallVec<[FocusId; 8]> {
327 let mut focus_path: SmallVec<[FocusId; 8]> = SmallVec::new();
328 let mut current_node_id = self.focusable_node_ids.get(&focus_id).copied();
329 while let Some(node_id) = current_node_id {
330 let node = self.node(node_id);
331 if let Some(focus_id) = node.focus_id {
332 focus_path.push(focus_id);
333 }
334 current_node_id = node.parent;
335 }
336 focus_path.reverse(); // Reverse the path so it goes from the root to the focused node.
337 focus_path
338 }
339
340 pub fn view_path(&self, view_id: EntityId) -> SmallVec<[EntityId; 8]> {
341 let mut view_path: SmallVec<[EntityId; 8]> = SmallVec::new();
342 let mut current_node_id = self.view_node_ids.get(&view_id).copied();
343 while let Some(node_id) = current_node_id {
344 let node = self.node(node_id);
345 if let Some(view_id) = node.view_id {
346 view_path.push(view_id);
347 }
348 current_node_id = node.parent;
349 }
350 view_path.reverse(); // Reverse the path so it goes from the root to the view node.
351 view_path
352 }
353
354 pub fn active_view_id(&self) -> Option<EntityId> {
355 self.view_stack.last().copied()
356 }
357
358 pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode {
359 &self.nodes[node_id.0]
360 }
361
362 fn active_node(&mut self) -> &mut DispatchNode {
363 let active_node_id = self.active_node_id();
364 &mut self.nodes[active_node_id.0]
365 }
366
367 pub fn focusable_node_id(&self, target: FocusId) -> Option<DispatchNodeId> {
368 self.focusable_node_ids.get(&target).copied()
369 }
370
371 pub fn root_node_id(&self) -> DispatchNodeId {
372 debug_assert!(!self.nodes.is_empty());
373 DispatchNodeId(0)
374 }
375
376 fn active_node_id(&self) -> DispatchNodeId {
377 *self.node_stack.last().unwrap()
378 }
379}