fret_ui_headless/
tooltip_intent.rs1use fret_core::PointerType;
2
3#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
7pub struct TooltipTriggerIntentGates {
8 pub has_pointer_move_opened: bool,
9 pub suppress_hover_open: bool,
10 pub suppress_focus_open: bool,
11}
12
13impl TooltipTriggerIntentGates {
14 pub fn trigger_hovered(self, hovered: bool) -> bool {
15 hovered && self.has_pointer_move_opened && !self.suppress_hover_open
16 }
17
18 pub fn trigger_focused(self, focused: bool) -> bool {
19 focused && !self.suppress_focus_open
20 }
21
22 pub fn on_left_hover(mut self, left_hover: bool) -> Self {
25 if left_hover && (self.has_pointer_move_opened || self.suppress_hover_open) {
26 self.has_pointer_move_opened = false;
27 self.suppress_hover_open = false;
28 }
29 self
30 }
31
32 pub fn on_focus_changed(mut self, focused: bool) -> Self {
34 if !focused && self.suppress_focus_open {
35 self.suppress_focus_open = false;
36 }
37 self
38 }
39
40 pub fn on_close_requested(mut self, close_requested: bool, focused: bool) -> (Self, bool) {
43 if !close_requested {
44 return (self, false);
45 }
46
47 if self.has_pointer_move_opened && !self.suppress_hover_open {
50 self.suppress_hover_open = true;
51 }
52
53 if focused && !self.suppress_focus_open {
56 self.suppress_focus_open = true;
57 }
58
59 (self, true)
60 }
61
62 pub fn on_pointer_down(mut self, pointer_type: PointerType) -> (Self, bool) {
66 let request_close = pointer_type != PointerType::Touch;
67 self.suppress_focus_open = true;
68 if self.has_pointer_move_opened {
69 self.suppress_hover_open = true;
70 }
71 (self, request_close)
72 }
73
74 pub fn on_activate(mut self) -> (Self, bool) {
78 self.suppress_focus_open = true;
79 (self, true)
80 }
81
82 pub fn on_escape(mut self) -> (Self, bool) {
86 self.suppress_focus_open = true;
87 (self, true)
88 }
89}
90
91#[cfg(test)]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn left_hover_resets_hover_gates() {
97 let st = TooltipTriggerIntentGates {
98 has_pointer_move_opened: true,
99 suppress_hover_open: true,
100 suppress_focus_open: false,
101 };
102 let out = st.on_left_hover(true);
103 assert_eq!(
104 out,
105 TooltipTriggerIntentGates {
106 has_pointer_move_opened: false,
107 suppress_hover_open: false,
108 suppress_focus_open: false,
109 }
110 );
111 }
112
113 #[test]
114 fn blur_clears_focus_suppression() {
115 let st = TooltipTriggerIntentGates {
116 has_pointer_move_opened: false,
117 suppress_hover_open: false,
118 suppress_focus_open: true,
119 };
120 assert_eq!(
121 st.on_focus_changed(false),
122 TooltipTriggerIntentGates {
123 suppress_focus_open: false,
124 ..st
125 }
126 );
127 }
128
129 #[test]
130 fn close_request_suppresses_focus_and_optionally_hover() {
131 let st = TooltipTriggerIntentGates {
132 has_pointer_move_opened: true,
133 suppress_hover_open: false,
134 suppress_focus_open: false,
135 };
136 let (out, clear) = st.on_close_requested(true, true);
137 assert!(clear);
138 assert!(out.suppress_focus_open);
139 assert!(out.suppress_hover_open);
140 assert!(out.has_pointer_move_opened);
141 }
142
143 #[test]
144 fn pointer_down_suppresses_focus_and_hover_when_pointer_opened() {
145 let st = TooltipTriggerIntentGates {
146 has_pointer_move_opened: true,
147 suppress_hover_open: false,
148 suppress_focus_open: false,
149 };
150 let (out, request_close) = st.on_pointer_down(PointerType::Mouse);
151 assert!(request_close);
152 assert!(out.suppress_focus_open);
153 assert!(out.suppress_hover_open);
154 }
155
156 #[test]
157 fn touch_pointer_down_does_not_request_close() {
158 let st = TooltipTriggerIntentGates::default();
159 let (_out, request_close) = st.on_pointer_down(PointerType::Touch);
160 assert!(!request_close);
161 }
162}