viewport_lib/interaction/input/
viewport_binding.rs1use super::action::Action;
4use super::binding::{KeyCode, Modifiers, MouseButton};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum ModifiersMatch {
9 Exact(Modifiers),
11 Contains(Modifiers),
13 Any,
15}
16
17impl ModifiersMatch {
18 pub fn matches(&self, mods: Modifiers) -> bool {
20 match self {
21 ModifiersMatch::Exact(required) => mods == *required,
22 ModifiersMatch::Contains(required) => {
23 (!required.alt || mods.alt)
25 && (!required.shift || mods.shift)
26 && (!required.ctrl || mods.ctrl)
27 }
28 ModifiersMatch::Any => true,
29 }
30 }
31}
32
33#[derive(Debug, Clone)]
35pub enum ViewportGesture {
36 Drag {
38 button: MouseButton,
40 modifiers: ModifiersMatch,
42 },
43 WheelY {
47 modifiers: ModifiersMatch,
49 },
50 WheelXY {
54 modifiers: ModifiersMatch,
56 },
57 KeyPress {
59 key: KeyCode,
61 modifiers: ModifiersMatch,
63 },
64 KeyHold {
66 key: KeyCode,
68 modifiers: ModifiersMatch,
70 },
71}
72
73#[derive(Debug, Clone)]
75pub struct ViewportBinding {
76 pub action: Action,
78 pub gesture: ViewportGesture,
80}
81
82impl ViewportBinding {
83 pub fn new(action: Action, gesture: ViewportGesture) -> Self {
85 Self { action, gesture }
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn exact_none_matches_no_modifiers() {
95 assert!(ModifiersMatch::Exact(Modifiers::NONE).matches(Modifiers::NONE));
96 }
97
98 #[test]
99 fn exact_none_rejects_alt() {
100 assert!(!ModifiersMatch::Exact(Modifiers::NONE).matches(Modifiers::ALT));
101 }
102
103 #[test]
104 fn exact_shift_matches_shift_only() {
105 assert!(ModifiersMatch::Exact(Modifiers::SHIFT).matches(Modifiers::SHIFT));
106 assert!(!ModifiersMatch::Exact(Modifiers::SHIFT).matches(Modifiers::NONE));
107 assert!(!ModifiersMatch::Exact(Modifiers::SHIFT).matches(Modifiers::CTRL_SHIFT));
108 }
109
110 #[test]
111 fn contains_shift_allows_extras() {
112 assert!(ModifiersMatch::Contains(Modifiers::SHIFT).matches(Modifiers::SHIFT));
113 assert!(ModifiersMatch::Contains(Modifiers::SHIFT).matches(Modifiers::CTRL_SHIFT));
114 assert!(!ModifiersMatch::Contains(Modifiers::SHIFT).matches(Modifiers::NONE));
115 assert!(!ModifiersMatch::Contains(Modifiers::SHIFT).matches(Modifiers::CTRL));
116 }
117
118 #[test]
119 fn contains_ctrl_shift_requires_both() {
120 assert!(ModifiersMatch::Contains(Modifiers::CTRL_SHIFT).matches(Modifiers::CTRL_SHIFT));
121 assert!(!ModifiersMatch::Contains(Modifiers::CTRL_SHIFT).matches(Modifiers::CTRL));
122 assert!(!ModifiersMatch::Contains(Modifiers::CTRL_SHIFT).matches(Modifiers::SHIFT));
123 }
124
125 #[test]
126 fn any_matches_everything() {
127 assert!(ModifiersMatch::Any.matches(Modifiers::NONE));
128 assert!(ModifiersMatch::Any.matches(Modifiers::ALT));
129 assert!(ModifiersMatch::Any.matches(Modifiers::CTRL_SHIFT));
130 }
131}