widgetry/
input.rs

1use geom::Duration;
2
3use crate::{Canvas, Event, Key, MultiKey, ScreenPt};
4
5// As we check for user input, record the input and the thing that would happen. This will let us
6// build up some kind of OSD of possible actions.
7pub struct UserInput {
8    pub(crate) event: Event,
9    pub(crate) event_consumed: bool,
10
11    lctrl_held: bool,
12}
13
14impl UserInput {
15    pub(crate) fn new(event: Event, canvas: &Canvas) -> UserInput {
16        UserInput {
17            event,
18            event_consumed: false,
19            lctrl_held: canvas.keys_held.contains(&Key::LeftControl),
20        }
21    }
22
23    pub fn pressed<MK: Into<Option<MultiKey>>>(&mut self, multikey: MK) -> bool {
24        let mk = if let Some(mk) = multikey.into() {
25            mk
26        } else {
27            return false;
28        };
29        if self.event_consumed {
30            return false;
31        }
32
33        if let Event::KeyPress(pressed) = self.event {
34            let same = match mk {
35                MultiKey::Normal(key) => pressed == key && !self.lctrl_held,
36                MultiKey::LCtrl(key) => pressed == key && self.lctrl_held,
37                MultiKey::Any(keys) => !self.lctrl_held && keys.contains(&pressed),
38            };
39            if same {
40                self.consume_event();
41                return true;
42            }
43        }
44        false
45    }
46
47    pub(crate) fn any_pressed(&mut self) -> Option<Key> {
48        if self.event_consumed {
49            return None;
50        }
51
52        if let Event::KeyPress(key) = self.event {
53            self.consume_event();
54            return Some(key);
55        }
56        None
57    }
58
59    pub fn key_released(&mut self, key: Key) -> bool {
60        if self.event_consumed {
61            return false;
62        }
63
64        if self.event == Event::KeyRelease(key) {
65            self.consume_event();
66            return true;
67        }
68        false
69    }
70
71    // No consuming for these?
72    // Only places looking at special drag behavior should use these two, otherwise prefer
73    // normal_left_click in EventCtx
74    pub fn left_mouse_button_pressed(&mut self) -> bool {
75        self.event == Event::LeftMouseButtonDown
76    }
77    pub fn left_mouse_button_released(&mut self) -> bool {
78        matches!(self.event, Event::LeftMouseButtonUp { .. })
79    }
80
81    pub fn left_mouse_double_clicked(&mut self) -> bool {
82        matches!(
83            self.event,
84            Event::LeftMouseButtonUp {
85                is_double_click: true
86            }
87        )
88    }
89
90    pub fn window_lost_cursor(&self) -> bool {
91        self.event == Event::WindowLostCursor
92    }
93
94    pub fn get_moved_mouse(&self) -> Option<ScreenPt> {
95        if let Event::MouseMovedTo(pt) = self.event {
96            return Some(pt);
97        }
98        None
99    }
100
101    pub fn get_mouse_scroll(&self) -> Option<(f64, f64)> {
102        if let Event::MouseWheelScroll(dx, dy) = self.event {
103            return Some((dx, dy));
104        }
105        None
106    }
107
108    pub fn is_window_resized(&self) -> bool {
109        matches!(self.event, Event::WindowResized(_))
110    }
111
112    pub fn nonblocking_is_update_event(&mut self) -> Option<Duration> {
113        if self.event_consumed {
114            return None;
115        }
116
117        if let Event::Update(dt) = self.event {
118            Some(dt)
119        } else {
120            None
121        }
122    }
123    pub fn use_update_event(&mut self) {
124        self.consume_event();
125        match self.event {
126            Event::Update(_) => {}
127            _ => panic!("Not an update event"),
128        }
129    }
130
131    pub(crate) fn consume_event(&mut self) {
132        assert!(!self.event_consumed);
133        self.event_consumed = true;
134    }
135    pub(crate) fn unconsume_event(&mut self) {
136        assert!(self.event_consumed);
137        self.event_consumed = false;
138    }
139
140    pub(crate) fn has_been_consumed(&self) -> bool {
141        self.event_consumed
142    }
143}