vizia_core/tree/
focus_iter.rs
1use crate::entity::Entity;
2use crate::prelude::Style;
3use crate::style::{Abilities, Display};
4use vizia_id::GenerationalId;
5use vizia_storage::{
6 DoubleEndedTreeTour, FocusTreeIterator, TourDirection, Tree, TreeExt, TreeTour,
7};
8
9pub(crate) fn is_navigatable(
11 tree: &Tree<Entity>,
12 style: &Style,
13 node: Entity,
14 lock_focus_to: Entity,
15) -> bool {
16 if style.disabled.get(node).cloned().unwrap_or_default() {
23 return false;
24 }
25
26 if style.display.get(node).copied().unwrap_or_default() == Display::None {
28 return false;
29 }
30
31 if !node.is_descendant_of(tree, lock_focus_to) {
33 return false;
34 }
35
36 if tree.is_ignored(node) {
38 return false;
39 }
40
41 style
42 .abilities
43 .get(node)
44 .map(|abilities| abilities.contains(Abilities::NAVIGABLE))
45 .unwrap_or(false)
46}
47
48pub(crate) fn focus_forward(
50 tree: &Tree<Entity>,
51 style: &Style,
52 node: Entity,
53 lock_focus_to: Entity,
54) -> Option<Entity> {
55 FocusTreeIterator::new(
56 tree,
57 DoubleEndedTreeTour::new(Some(node), Some(Entity::root())),
58 |node| {
59 style.display.get(node).copied().unwrap_or_default() == Display::None
60 },
62 )
63 .skip(1)
64 .find(|node| is_navigatable(tree, style, *node, lock_focus_to))
65}
66
67pub(crate) fn focus_backward(
69 tree: &Tree<Entity>,
70 style: &Style,
71 node: Entity,
72 lock_focus_to: Entity,
73) -> Option<Entity> {
74 let mut iter = FocusTreeIterator::new(
75 tree,
76 DoubleEndedTreeTour::new_raw(
77 TreeTour::new(Some(Entity::root())),
78 TreeTour::with_direction(Some(node), TourDirection::Leaving),
79 ),
80 |node| {
81 for ancestor in node.parent_iter(tree) {
84 if style.display.get(ancestor).copied().unwrap_or_default() == Display::None {
85 return true;
86 }
87 }
88
89 false
90 },
91 );
92 iter.next_back();
93 iter.filter(|node| is_navigatable(tree, style, *node, lock_focus_to)).next_back()
94}