1use crate::*;
7use std::time::Instant;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum SimplifiedGestureType {
12 None,
14 Pinch,
16 Rotation,
18 Pan,
20 MultiTouch,
22}
23
24#[derive(Debug, Clone, PartialEq)]
26pub struct SimplifiedGestureConfig {
27 pub max_touches: usize,
29 pub min_distance: f64,
31 pub timeout: u64,
33 pub enable_pinch: bool,
35 pub enable_rotation: bool,
37 pub enable_pan: bool,
39}
40
41#[derive(Debug, Clone, PartialEq)]
43pub struct SimplifiedGestureResult {
44 pub gesture_type: SimplifiedGestureType,
46 pub scale: Option<f64>,
48 pub rotation: Option<f64>,
50 pub translation: Option<SimplifiedVector2D>,
52 pub velocity: Option<SimplifiedVector2D>,
54 pub center: Option<SimplifiedVector2D>,
56 pub confidence: f64,
58 pub duration: u64,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq)]
64pub struct SimplifiedVector2D {
65 pub x: f64,
66 pub y: f64,
67}
68
69#[derive(Debug, Clone, Copy, PartialEq)]
71pub struct SimplifiedGestureBounds {
72 pub min_x: f64,
73 pub max_x: f64,
74 pub min_y: f64,
75 pub max_y: f64,
76}
77
78#[derive(Debug, Clone, PartialEq)]
80pub struct SimplifiedGestureData {
81 pub gesture_type: SimplifiedGestureType,
82 pub touch_count: usize,
83 pub is_active: bool,
84 pub center: Option<SimplifiedVector2D>,
85 pub bounds: Option<SimplifiedGestureBounds>,
86 pub distance: Option<f64>,
87 pub angle: Option<f64>,
88 pub confidence: f64,
89 pub duration: u64,
90}
91
92pub struct SimplifiedGestureDetector {
98 internal_detector: MultiTouchGestureDetector,
100 current_gesture: SimplifiedGestureType,
102 gesture_start: Option<Instant>,
104 last_result: SimplifiedGestureResult,
106}
107
108impl SimplifiedGestureDetector {
109 pub fn new() -> Self {
111 Self::with_config(SimplifiedGestureConfig::default())
112 }
113
114 pub fn with_config(config: SimplifiedGestureConfig) -> Self {
116 let internal_config = GestureConfig {
117 basic_gestures: true,
118 multi_touch: true,
119 pinch_to_zoom: config.enable_pinch,
120 rotation: config.enable_rotation,
121 sensitivity: 0.5,
122 min_distance: config.min_distance,
123 max_touches: config.max_touches,
124 timeout_ms: config.timeout,
125 };
126
127 Self {
128 internal_detector: MultiTouchGestureDetector::new(internal_config),
129 current_gesture: SimplifiedGestureType::None,
130 gesture_start: None,
131 last_result: SimplifiedGestureResult::default(),
132 }
133 }
134
135 pub fn handle_touch_start(&mut self, touches: Vec<TouchPoint>) -> SimplifiedGestureResult {
137 let result = self.internal_detector.handle_touch_start(touches);
138 self.current_gesture = self.convert_gesture_type(result.gesture_type.clone());
139
140 if self.current_gesture != SimplifiedGestureType::None {
141 self.gesture_start = Some(Instant::now());
142 }
143
144 self.last_result = self.create_simplified_result(result);
145 self.last_result.clone()
146 }
147
148 pub fn handle_touch_move(&mut self, touches: Vec<TouchPoint>) -> SimplifiedGestureResult {
150 let result = self.internal_detector.handle_touch_move(touches);
151 self.current_gesture = self.convert_gesture_type(result.gesture_type.clone());
152
153 self.last_result = self.create_simplified_result(result);
154 self.last_result.clone()
155 }
156
157 pub fn handle_touch_end(&mut self, touch_ids: Vec<u64>) -> SimplifiedGestureResult {
159 let touches: Vec<TouchPoint> = touch_ids
161 .into_iter()
162 .map(|id| TouchPoint {
163 id,
164 x: 0.0,
165 y: 0.0,
166 pressure: 0.0,
167 timestamp: std::time::SystemTime::now()
168 .duration_since(std::time::UNIX_EPOCH)
169 .unwrap()
170 .as_millis() as u64,
171 })
172 .collect();
173
174 let result = self.internal_detector.handle_touch_end(touches);
175 self.current_gesture = SimplifiedGestureType::None;
176 self.gesture_start = None;
177
178 self.last_result = self.create_simplified_result(result);
179 self.last_result.clone()
180 }
181
182 pub fn cancel(&mut self) {
184 self.internal_detector.reset();
185 self.current_gesture = SimplifiedGestureType::None;
186 self.gesture_start = None;
187 self.last_result = SimplifiedGestureResult::default();
188 }
189
190 pub fn reset(&mut self) {
192 self.internal_detector.reset();
193 self.current_gesture = SimplifiedGestureType::None;
194 self.gesture_start = None;
195 self.last_result = SimplifiedGestureResult::default();
196 }
197
198 pub fn is_active(&self) -> bool {
200 self.internal_detector.is_active()
201 }
202
203 pub fn touch_count(&self) -> usize {
205 self.internal_detector.get_state().touches.len()
206 }
207
208 pub fn gesture_type(&self) -> SimplifiedGestureType {
210 self.current_gesture
211 }
212
213 pub fn get_gesture_data(&self) -> Option<SimplifiedGestureData> {
215 if !self.is_active() {
216 return None;
217 }
218
219 Some(SimplifiedGestureData {
220 gesture_type: self.current_gesture,
221 touch_count: self.touch_count(),
222 is_active: self.is_active(),
223 center: self.get_center(),
224 bounds: self.get_bounds(),
225 distance: self.get_distance(),
226 angle: self.get_angle(),
227 confidence: self.get_confidence(),
228 duration: self.get_duration(),
229 })
230 }
231
232 pub fn get_confidence(&self) -> f64 {
234 0.8
236 }
237
238 pub fn get_center(&self) -> Option<SimplifiedVector2D> {
240 if self.touch_count() < 2 {
241 return None;
242 }
243
244 let state = self.internal_detector.get_state();
245 let touches: Vec<&TouchPoint> = state.touches.values().collect();
246
247 if touches.len() < 2 {
248 return None;
249 }
250
251 let center_x = touches.iter().map(|t| t.x).sum::<f64>() / touches.len() as f64;
252 let center_y = touches.iter().map(|t| t.y).sum::<f64>() / touches.len() as f64;
253
254 Some(SimplifiedVector2D {
255 x: center_x,
256 y: center_y,
257 })
258 }
259
260 pub fn get_bounds(&self) -> Option<SimplifiedGestureBounds> {
262 if self.touch_count() < 2 {
263 return None;
264 }
265
266 let state = self.internal_detector.get_state();
267 let touches: Vec<&TouchPoint> = state.touches.values().collect();
268
269 if touches.is_empty() {
270 return None;
271 }
272
273 let min_x = touches.iter().map(|t| t.x).fold(f64::INFINITY, f64::min);
274 let max_x = touches
275 .iter()
276 .map(|t| t.x)
277 .fold(f64::NEG_INFINITY, f64::max);
278 let min_y = touches.iter().map(|t| t.y).fold(f64::INFINITY, f64::min);
279 let max_y = touches
280 .iter()
281 .map(|t| t.y)
282 .fold(f64::NEG_INFINITY, f64::max);
283
284 Some(SimplifiedGestureBounds {
285 min_x,
286 max_x,
287 min_y,
288 max_y,
289 })
290 }
291
292 pub fn get_distance(&self) -> Option<f64> {
294 if self.touch_count() < 2 {
295 return None;
296 }
297
298 let state = self.internal_detector.get_state();
299 let touches: Vec<&TouchPoint> = state.touches.values().collect();
300
301 if touches.len() < 2 {
302 return None;
303 }
304
305 let dx = touches[1].x - touches[0].x;
306 let dy = touches[1].y - touches[0].y;
307 Some((dx * dx + dy * dy).sqrt())
308 }
309
310 pub fn get_angle(&self) -> Option<f64> {
312 if self.touch_count() < 2 {
313 return None;
314 }
315
316 let state = self.internal_detector.get_state();
317 let touches: Vec<&TouchPoint> = state.touches.values().collect();
318
319 if touches.len() < 2 {
320 return None;
321 }
322
323 let dx = touches[1].x - touches[0].x;
324 let dy = touches[1].y - touches[0].y;
325 Some(dy.atan2(dx).to_degrees())
326 }
327
328 pub fn get_duration(&self) -> u64 {
330 if let Some(start) = self.gesture_start {
331 start.elapsed().as_millis() as u64
332 } else {
333 0
334 }
335 }
336
337 pub fn update_config(&mut self, config: SimplifiedGestureConfig) {
339 let internal_config = GestureConfig {
340 basic_gestures: true,
341 multi_touch: true,
342 pinch_to_zoom: config.enable_pinch,
343 rotation: config.enable_rotation,
344 sensitivity: 0.5,
345 min_distance: config.min_distance,
346 max_touches: config.max_touches,
347 timeout_ms: config.timeout,
348 };
349
350 self.internal_detector.update_config(internal_config);
351 }
352
353 pub fn get_config(&self) -> SimplifiedGestureConfig {
355 SimplifiedGestureConfig::default()
358 }
359
360 fn convert_gesture_type(&self, gesture_type: MultiTouchGestureType) -> SimplifiedGestureType {
362 match gesture_type {
363 MultiTouchGestureType::None => SimplifiedGestureType::None,
364 MultiTouchGestureType::Pinch => SimplifiedGestureType::Pinch,
365 MultiTouchGestureType::Rotation => SimplifiedGestureType::Rotation,
366 MultiTouchGestureType::MultiSwipe => SimplifiedGestureType::Pan,
367 MultiTouchGestureType::PinchAndRotate => SimplifiedGestureType::MultiTouch,
368 MultiTouchGestureType::MultiTap => SimplifiedGestureType::None,
369 }
370 }
371
372 fn create_simplified_result(&self, result: GestureResult) -> SimplifiedGestureResult {
374 SimplifiedGestureResult {
375 gesture_type: self.convert_gesture_type(result.gesture_type),
376 scale: None, rotation: None, translation: None, velocity: None, center: self.get_center(),
381 confidence: result.confidence,
382 duration: self.get_duration(),
383 }
384 }
385}
386
387impl Default for SimplifiedGestureDetector {
388 fn default() -> Self {
389 Self::new()
390 }
391}
392
393impl Clone for SimplifiedGestureDetector {
394 fn clone(&self) -> Self {
395 let config = self.get_config();
397 Self {
398 internal_detector: MultiTouchGestureDetector::new(GestureConfig {
399 basic_gestures: true,
400 multi_touch: true,
401 pinch_to_zoom: config.enable_pinch,
402 rotation: config.enable_rotation,
403 sensitivity: 0.5,
404 min_distance: config.min_distance,
405 max_touches: config.max_touches,
406 timeout_ms: config.timeout,
407 }),
408 current_gesture: self.current_gesture,
409 gesture_start: self.gesture_start,
410 last_result: self.last_result.clone(),
411 }
412 }
413}
414
415impl std::fmt::Debug for SimplifiedGestureDetector {
416 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
417 f.debug_struct("SimplifiedGestureDetector")
418 .field("is_active", &self.is_active())
419 .field("touch_count", &self.touch_count())
420 .field("gesture_type", &self.gesture_type())
421 .finish()
422 }
423}
424
425impl Default for SimplifiedGestureConfig {
426 fn default() -> Self {
427 Self {
428 max_touches: 5,
429 min_distance: 10.0,
430 timeout: 1000,
431 enable_pinch: true,
432 enable_rotation: true,
433 enable_pan: true,
434 }
435 }
436}
437
438impl SimplifiedGestureConfig {
439 pub fn new() -> Self {
441 Self::default()
442 }
443
444 pub fn max_touches(mut self, max_touches: usize) -> Self {
446 self.max_touches = max_touches;
447 self
448 }
449
450 pub fn min_distance(mut self, min_distance: f64) -> Self {
452 self.min_distance = min_distance;
453 self
454 }
455
456 pub fn timeout(mut self, timeout: u64) -> Self {
458 self.timeout = timeout;
459 self
460 }
461
462 pub fn enable_pinch(mut self, enable: bool) -> Self {
464 self.enable_pinch = enable;
465 self
466 }
467
468 pub fn enable_rotation(mut self, enable: bool) -> Self {
470 self.enable_rotation = enable;
471 self
472 }
473
474 pub fn enable_pan(mut self, enable: bool) -> Self {
476 self.enable_pan = enable;
477 self
478 }
479}
480
481impl Default for SimplifiedGestureResult {
482 fn default() -> Self {
483 Self {
484 gesture_type: SimplifiedGestureType::None,
485 scale: None,
486 rotation: None,
487 translation: None,
488 velocity: None,
489 center: None,
490 confidence: 0.0,
491 duration: 0,
492 }
493 }
494}
495
496#[cfg(test)]
497mod tests {
498 use super::*;
499
500 #[test]
501 fn test_simplified_gesture_detector_creation() {
502 let detector = SimplifiedGestureDetector::new();
503 assert!(!detector.is_active());
504 assert_eq!(detector.touch_count(), 0);
505 assert_eq!(detector.gesture_type(), SimplifiedGestureType::None);
506 }
507
508 #[test]
509 fn test_simplified_gesture_detector_with_config() {
510 let config = SimplifiedGestureConfig::new()
511 .max_touches(3)
512 .min_distance(5.0);
513
514 let detector = SimplifiedGestureDetector::with_config(config);
515 assert!(!detector.is_active());
516 assert_eq!(detector.touch_count(), 0);
517 }
518
519 #[test]
520 fn test_simplified_gesture_config_fluent_api() {
521 let config = SimplifiedGestureConfig::new()
522 .max_touches(5)
523 .min_distance(10.0)
524 .timeout(1000)
525 .enable_pinch(true)
526 .enable_rotation(false)
527 .enable_pan(true);
528
529 assert_eq!(config.max_touches, 5);
530 assert_eq!(config.min_distance, 10.0);
531 assert_eq!(config.timeout, 1000);
532 assert!(config.enable_pinch);
533 assert!(!config.enable_rotation);
534 assert!(config.enable_pan);
535 }
536
537 #[test]
538 fn test_simplified_gesture_detector_clone() {
539 let detector1 = SimplifiedGestureDetector::new();
540 let detector2 = detector1.clone();
541
542 assert_eq!(detector1.is_active(), detector2.is_active());
543 assert_eq!(detector1.touch_count(), detector2.touch_count());
544 assert_eq!(detector1.gesture_type(), detector2.gesture_type());
545 }
546
547 #[test]
548 fn test_simplified_gesture_detector_debug() {
549 let detector = SimplifiedGestureDetector::new();
550 let debug_str = format!("{:?}", detector);
551 assert!(debug_str.contains("SimplifiedGestureDetector"));
552 assert!(debug_str.contains("is_active"));
553 assert!(debug_str.contains("touch_count"));
554 assert!(debug_str.contains("gesture_type"));
555 }
556}