freya_core/
events_combos.rs1use std::time::{
2 Duration,
3 Instant,
4};
5
6use torin::prelude::CursorPoint;
7
8use crate::{
9 integration::ScopeId,
10 prelude::{
11 State,
12 *,
13 },
14};
15
16#[derive(Clone, Copy, PartialEq)]
17pub struct EventsCombos {
18 pub(crate) last_press: State<Option<(Instant, CursorPoint, u8)>>,
19}
20
21impl EventsCombos {
22 pub fn get() -> Self {
23 match try_consume_root_context() {
24 Some(rt) => rt,
25 None => {
26 let context_menu_state = EventsCombos {
27 last_press: State::create_in_scope(None, ScopeId::ROOT),
28 };
29 provide_context_for_scope_id(context_menu_state, ScopeId::ROOT);
30 context_menu_state
31 }
32 }
33 }
34
35 pub fn moved(location: CursorPoint) {
37 let mut combos = Self::get();
38 let dragged_away = matches!(
39 &*combos.last_press.read(),
40 Some((_, last_location, _)) if last_location.distance_to(location) > LOCATION_THRESHOLD
41 );
42 if dragged_away {
43 combos.last_press.set(None);
44 }
45 }
46
47 pub fn pressed(location: CursorPoint) -> PressEventType {
48 let mut combos = Self::get();
49 let (event_type, click_count) = match &*combos.last_press.read() {
50 Some((inst, last_location, count)) if inst.elapsed() <= MULTI_PRESS_ELAPSED => {
51 if last_location.distance_to(location) <= LOCATION_THRESHOLD {
52 match count {
53 1 => (PressEventType::Double, 2),
54 2 => (PressEventType::Triple, 3),
55 3 => (PressEventType::Quadruple, 4),
56 _ => (PressEventType::Single, 1),
57 }
58 } else {
59 (PressEventType::Single, 1)
60 }
61 }
62 _ => (PressEventType::Single, 1),
63 };
64 combos
65 .last_press
66 .set(Some((Instant::now(), location, click_count)));
67 event_type
68 }
69}
70
71const LOCATION_THRESHOLD: f64 = 5.0;
72const MULTI_PRESS_ELAPSED: Duration = Duration::from_millis(500);
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum PressEventType {
76 Single,
77 Double,
78 Triple,
79 Quadruple,
80}
81
82impl PressEventType {
83 pub fn is_single(&self) -> bool {
84 matches!(self, Self::Single)
85 }
86
87 pub fn is_double(&self) -> bool {
88 matches!(self, Self::Double)
89 }
90
91 pub fn is_triple(&self) -> bool {
92 matches!(self, Self::Triple)
93 }
94
95 pub fn is_quadruple(&self) -> bool {
96 matches!(self, Self::Quadruple)
97 }
98}