forked from lapce/floem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnav.rs
77 lines (72 loc) · 2.91 KB
/
nav.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use floem_winit::keyboard::NamedKey;
use kurbo::{Point, Rect};
use crate::{
context::AppState,
id::Id,
view::{view_tab_navigation, Widget},
};
pub(crate) fn view_arrow_navigation(key: NamedKey, app_state: &mut AppState, view: &dyn Widget) {
let focused = match app_state.focus {
Some(id) => id,
None => {
view_tab_navigation(
view,
app_state,
matches!(key, NamedKey::ArrowUp | NamedKey::ArrowLeft),
);
return;
}
};
let rect = app_state.get_layout_rect(focused).inflate(10.0, 10.0);
let center = rect.center();
let intersect_target = match key {
NamedKey::ArrowUp => Rect::new(rect.x0, f64::NEG_INFINITY, rect.x1, center.y),
NamedKey::ArrowDown => Rect::new(rect.x0, center.y, rect.x1, f64::INFINITY),
NamedKey::ArrowLeft => Rect::new(f64::NEG_INFINITY, rect.y0, center.x, rect.y1),
NamedKey::ArrowRight => Rect::new(center.x, rect.y0, f64::INFINITY, rect.y1),
_ => panic!(),
};
let center_target = match key {
NamedKey::ArrowUp => {
Rect::new(f64::NEG_INFINITY, f64::NEG_INFINITY, f64::INFINITY, rect.y0)
}
NamedKey::ArrowDown => Rect::new(f64::NEG_INFINITY, rect.y1, f64::INFINITY, f64::INFINITY),
NamedKey::ArrowLeft => {
Rect::new(f64::NEG_INFINITY, f64::NEG_INFINITY, rect.x0, f64::INFINITY)
}
NamedKey::ArrowRight => Rect::new(rect.x1, f64::NEG_INFINITY, f64::INFINITY, f64::INFINITY),
_ => panic!(),
};
let mut keyboard_navigable: Vec<Id> = app_state.keyboard_navigable.iter().copied().collect();
keyboard_navigable.retain(|id| {
let layout = app_state.get_layout_rect(*id);
!layout.intersect(intersect_target).is_empty()
&& center_target.contains(layout.center())
&& app_state.can_focus(*id)
&& *id != focused
});
let mut new_focus = None;
for id in keyboard_navigable {
let id_rect = app_state.get_layout_rect(id);
let id_center = id_rect.center();
let id_edge = match key {
NamedKey::ArrowUp => Point::new(id_center.x, id_rect.y1),
NamedKey::ArrowDown => Point::new(id_center.x, id_rect.y0),
NamedKey::ArrowLeft => Point::new(id_rect.x1, id_center.y),
NamedKey::ArrowRight => Point::new(id_rect.x0, id_center.y),
_ => panic!(),
};
let id_distance = center.distance_squared(id_edge);
if let Some((_, distance)) = new_focus {
if id_distance < distance {
new_focus = Some((id, id_distance));
}
} else {
new_focus = Some((id, id_distance));
}
}
if let Some((id, _)) = new_focus {
app_state.clear_focus();
app_state.update_focus(id, true);
}
}