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,
67 pub y: f64,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq)]
73pub struct SimplifiedGestureBounds {
74 pub min_x: f64,
76 pub max_x: f64,
78 pub min_y: f64,
80 pub max_y: f64,
82}
83
84#[derive(Debug, Clone, PartialEq)]
86pub struct SimplifiedGestureData {
87 pub gesture_type: SimplifiedGestureType,
89 pub touch_count: usize,
91 pub is_active: bool,
93 pub center: Option<SimplifiedVector2D>,
95 pub bounds: Option<SimplifiedGestureBounds>,
97 pub distance: Option<f64>,
99 pub angle: Option<f64>,
101 pub confidence: f64,
103 pub duration: u64,
105}
106
107pub struct SimplifiedGestureDetector {
113 internal_detector: MultiTouchGestureDetector,
115 current_gesture: SimplifiedGestureType,
117 gesture_start: Option<Instant>,
119 last_result: SimplifiedGestureResult,
121}
122
123impl SimplifiedGestureDetector {
124 pub fn new() -> Self {
126 Self::with_config(SimplifiedGestureConfig::default())
127 }
128
129 pub fn with_config(config: SimplifiedGestureConfig) -> Self {
131 let internal_config = GestureConfig {
132 basic_gestures: true,
133 multi_touch: true,
134 pinch_to_zoom: config.enable_pinch,
135 rotation: config.enable_rotation,
136 sensitivity: 0.5,
137 min_distance: config.min_distance,
138 max_touches: config.max_touches,
139 timeout_ms: config.timeout,
140 };
141
142 Self {
143 internal_detector: MultiTouchGestureDetector::new(internal_config),
144 current_gesture: SimplifiedGestureType::None,
145 gesture_start: None,
146 last_result: SimplifiedGestureResult::default(),
147 }
148 }
149
150 pub fn handle_touch_start(&mut self, touches: Vec<TouchPoint>) -> SimplifiedGestureResult {
152 let result = self.internal_detector.handle_touch_start(touches);
153 self.current_gesture = self.convert_gesture_type(result.gesture_type.clone());
154
155 if self.current_gesture != SimplifiedGestureType::None {
156 self.gesture_start = Some(Instant::now());
157 }
158
159 self.last_result = self.create_simplified_result(result);
160 self.last_result.clone()
161 }
162
163 pub fn handle_touch_move(&mut self, touches: Vec<TouchPoint>) -> SimplifiedGestureResult {
165 let result = self.internal_detector.handle_touch_move(touches);
166 self.current_gesture = self.convert_gesture_type(result.gesture_type.clone());
167
168 self.last_result = self.create_simplified_result(result);
169 self.last_result.clone()
170 }
171
172 pub fn handle_touch_end(&mut self, touch_ids: Vec<u64>) -> SimplifiedGestureResult {
174 let touches: Vec<TouchPoint> = touch_ids
176 .into_iter()
177 .map(|id| TouchPoint {
178 id,
179 x: 0.0,
180 y: 0.0,
181 pressure: 0.0,
182 timestamp: std::time::SystemTime::now()
183 .duration_since(std::time::UNIX_EPOCH)
184 .unwrap()
185 .as_millis() as u64,
186 })
187 .collect();
188
189 let result = self.internal_detector.handle_touch_end(touches);
190 self.current_gesture = SimplifiedGestureType::None;
191 self.gesture_start = None;
192
193 self.last_result = self.create_simplified_result(result);
194 self.last_result.clone()
195 }
196
197 pub fn cancel(&mut self) {
199 self.internal_detector.reset();
200 self.current_gesture = SimplifiedGestureType::None;
201 self.gesture_start = None;
202 self.last_result = SimplifiedGestureResult::default();
203 }
204
205 pub fn reset(&mut self) {
207 self.internal_detector.reset();
208 self.current_gesture = SimplifiedGestureType::None;
209 self.gesture_start = None;
210 self.last_result = SimplifiedGestureResult::default();
211 }
212
213 pub fn is_active(&self) -> bool {
215 self.internal_detector.is_active()
216 }
217
218 pub fn touch_count(&self) -> usize {
220 self.internal_detector.get_state().touches.len()
221 }
222
223 pub fn gesture_type(&self) -> SimplifiedGestureType {
225 self.current_gesture
226 }
227
228 pub fn get_gesture_data(&self) -> Option<SimplifiedGestureData> {
230 if !self.is_active() {
231 return None;
232 }
233
234 Some(SimplifiedGestureData {
235 gesture_type: self.current_gesture,
236 touch_count: self.touch_count(),
237 is_active: self.is_active(),
238 center: self.get_center(),
239 bounds: self.get_bounds(),
240 distance: self.get_distance(),
241 angle: self.get_angle(),
242 confidence: self.get_confidence(),
243 duration: self.get_duration(),
244 })
245 }
246
247 pub fn get_confidence(&self) -> f64 {
249 0.8
251 }
252
253 pub fn get_center(&self) -> Option<SimplifiedVector2D> {
255 if self.touch_count() < 2 {
256 return None;
257 }
258
259 let state = self.internal_detector.get_state();
260 let touches: Vec<&TouchPoint> = state.touches.values().collect();
261
262 if touches.len() < 2 {
263 return None;
264 }
265
266 let center_x = touches.iter().map(|t| t.x).sum::<f64>() / touches.len() as f64;
267 let center_y = touches.iter().map(|t| t.y).sum::<f64>() / touches.len() as f64;
268
269 Some(SimplifiedVector2D {
270 x: center_x,
271 y: center_y,
272 })
273 }
274
275 pub fn get_bounds(&self) -> Option<SimplifiedGestureBounds> {
277 if self.touch_count() < 2 {
278 return None;
279 }
280
281 let state = self.internal_detector.get_state();
282 let touches: Vec<&TouchPoint> = state.touches.values().collect();
283
284 if touches.is_empty() {
285 return None;
286 }
287
288 let min_x = touches.iter().map(|t| t.x).fold(f64::INFINITY, f64::min);
289 let max_x = touches
290 .iter()
291 .map(|t| t.x)
292 .fold(f64::NEG_INFINITY, f64::max);
293 let min_y = touches.iter().map(|t| t.y).fold(f64::INFINITY, f64::min);
294 let max_y = touches
295 .iter()
296 .map(|t| t.y)
297 .fold(f64::NEG_INFINITY, f64::max);
298
299 Some(SimplifiedGestureBounds {
300 min_x,
301 max_x,
302 min_y,
303 max_y,
304 })
305 }
306
307 pub fn get_distance(&self) -> Option<f64> {
309 if self.touch_count() < 2 {
310 return None;
311 }
312
313 let state = self.internal_detector.get_state();
314 let touches: Vec<&TouchPoint> = state.touches.values().collect();
315
316 if touches.len() < 2 {
317 return None;
318 }
319
320 let dx = touches[1].x - touches[0].x;
321 let dy = touches[1].y - touches[0].y;
322 Some((dx * dx + dy * dy).sqrt())
323 }
324
325 pub fn get_angle(&self) -> Option<f64> {
327 if self.touch_count() < 2 {
328 return None;
329 }
330
331 let state = self.internal_detector.get_state();
332 let touches: Vec<&TouchPoint> = state.touches.values().collect();
333
334 if touches.len() < 2 {
335 return None;
336 }
337
338 let dx = touches[1].x - touches[0].x;
339 let dy = touches[1].y - touches[0].y;
340 Some(dy.atan2(dx).to_degrees())
341 }
342
343 pub fn get_duration(&self) -> u64 {
345 if let Some(start) = self.gesture_start {
346 start.elapsed().as_millis() as u64
347 } else {
348 0
349 }
350 }
351
352 pub fn update_config(&mut self, config: SimplifiedGestureConfig) {
354 let internal_config = GestureConfig {
355 basic_gestures: true,
356 multi_touch: true,
357 pinch_to_zoom: config.enable_pinch,
358 rotation: config.enable_rotation,
359 sensitivity: 0.5,
360 min_distance: config.min_distance,
361 max_touches: config.max_touches,
362 timeout_ms: config.timeout,
363 };
364
365 self.internal_detector.update_config(internal_config);
366 }
367
368 pub fn get_config(&self) -> SimplifiedGestureConfig {
370 SimplifiedGestureConfig::default()
373 }
374
375 fn convert_gesture_type(&self, gesture_type: MultiTouchGestureType) -> SimplifiedGestureType {
377 match gesture_type {
378 MultiTouchGestureType::None => SimplifiedGestureType::None,
379 MultiTouchGestureType::Pinch => SimplifiedGestureType::Pinch,
380 MultiTouchGestureType::Rotation => SimplifiedGestureType::Rotation,
381 MultiTouchGestureType::MultiSwipe => SimplifiedGestureType::Pan,
382 MultiTouchGestureType::PinchAndRotate => SimplifiedGestureType::MultiTouch,
383 MultiTouchGestureType::MultiTap => SimplifiedGestureType::None,
384 }
385 }
386
387 fn create_simplified_result(&self, result: GestureResult) -> SimplifiedGestureResult {
389 SimplifiedGestureResult {
390 gesture_type: self.convert_gesture_type(result.gesture_type),
391 scale: None, rotation: None, translation: None, velocity: None, center: self.get_center(),
396 confidence: result.confidence,
397 duration: self.get_duration(),
398 }
399 }
400}
401
402impl Default for SimplifiedGestureDetector {
403 fn default() -> Self {
404 Self::new()
405 }
406}
407
408impl Clone for SimplifiedGestureDetector {
409 fn clone(&self) -> Self {
410 let config = self.get_config();
412 Self {
413 internal_detector: MultiTouchGestureDetector::new(GestureConfig {
414 basic_gestures: true,
415 multi_touch: true,
416 pinch_to_zoom: config.enable_pinch,
417 rotation: config.enable_rotation,
418 sensitivity: 0.5,
419 min_distance: config.min_distance,
420 max_touches: config.max_touches,
421 timeout_ms: config.timeout,
422 }),
423 current_gesture: self.current_gesture,
424 gesture_start: self.gesture_start,
425 last_result: self.last_result.clone(),
426 }
427 }
428}
429
430impl std::fmt::Debug for SimplifiedGestureDetector {
431 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
432 f.debug_struct("SimplifiedGestureDetector")
433 .field("is_active", &self.is_active())
434 .field("touch_count", &self.touch_count())
435 .field("gesture_type", &self.gesture_type())
436 .finish()
437 }
438}
439
440impl Default for SimplifiedGestureConfig {
441 fn default() -> Self {
442 Self {
443 max_touches: 5,
444 min_distance: 10.0,
445 timeout: 1000,
446 enable_pinch: true,
447 enable_rotation: true,
448 enable_pan: true,
449 }
450 }
451}
452
453impl SimplifiedGestureConfig {
454 pub fn new() -> Self {
456 Self::default()
457 }
458
459 pub fn max_touches(mut self, max_touches: usize) -> Self {
461 self.max_touches = max_touches;
462 self
463 }
464
465 pub fn min_distance(mut self, min_distance: f64) -> Self {
467 self.min_distance = min_distance;
468 self
469 }
470
471 pub fn timeout(mut self, timeout: u64) -> Self {
473 self.timeout = timeout;
474 self
475 }
476
477 pub fn enable_pinch(mut self, enable: bool) -> Self {
479 self.enable_pinch = enable;
480 self
481 }
482
483 pub fn enable_rotation(mut self, enable: bool) -> Self {
485 self.enable_rotation = enable;
486 self
487 }
488
489 pub fn enable_pan(mut self, enable: bool) -> Self {
491 self.enable_pan = enable;
492 self
493 }
494}
495
496impl Default for SimplifiedGestureResult {
497 fn default() -> Self {
498 Self {
499 gesture_type: SimplifiedGestureType::None,
500 scale: None,
501 rotation: None,
502 translation: None,
503 velocity: None,
504 center: None,
505 confidence: 0.0,
506 duration: 0,
507 }
508 }
509}
510
511#[cfg(test)]
512mod tests {
513 use super::*;
514
515 #[test]
516 fn test_simplified_gesture_detector_creation() {
517 let detector = SimplifiedGestureDetector::new();
518 assert!(!detector.is_active());
519 assert_eq!(detector.touch_count(), 0);
520 assert_eq!(detector.gesture_type(), SimplifiedGestureType::None);
521 }
522
523 #[test]
524 fn test_simplified_gesture_detector_with_config() {
525 let config = SimplifiedGestureConfig::new()
526 .max_touches(3)
527 .min_distance(5.0);
528
529 let detector = SimplifiedGestureDetector::with_config(config);
530 assert!(!detector.is_active());
531 assert_eq!(detector.touch_count(), 0);
532 }
533
534 #[test]
535 fn test_simplified_gesture_config_fluent_api() {
536 let config = SimplifiedGestureConfig::new()
537 .max_touches(5)
538 .min_distance(10.0)
539 .timeout(1000)
540 .enable_pinch(true)
541 .enable_rotation(false)
542 .enable_pan(true);
543
544 assert_eq!(config.max_touches, 5);
545 assert_eq!(config.min_distance, 10.0);
546 assert_eq!(config.timeout, 1000);
547 assert!(config.enable_pinch);
548 assert!(!config.enable_rotation);
549 assert!(config.enable_pan);
550 }
551
552 #[test]
553 fn test_simplified_gesture_detector_clone() {
554 let detector1 = SimplifiedGestureDetector::new();
555 let detector2 = detector1.clone();
556
557 assert_eq!(detector1.is_active(), detector2.is_active());
558 assert_eq!(detector1.touch_count(), detector2.touch_count());
559 assert_eq!(detector1.gesture_type(), detector2.gesture_type());
560 }
561
562 #[test]
563 fn test_simplified_gesture_detector_debug() {
564 let detector = SimplifiedGestureDetector::new();
565 let debug_str = format!("{:?}", detector);
566 assert!(debug_str.contains("SimplifiedGestureDetector"));
567 assert!(debug_str.contains("is_active"));
568 assert!(debug_str.contains("touch_count"));
569 assert!(debug_str.contains("gesture_type"));
570 }
571}