1use self::mouse::Mouse;
11use super::keyboard::ModifierKey;
12use fnv;
13use position::Point;
14use utils;
15use widget;
16
17#[derive(Clone, Debug, PartialEq)]
24pub struct State {
25 pub mouse: Mouse,
27 pub touch: fnv::FnvHashMap<super::touch::Id, self::touch::Touch>,
29 pub widget_capturing_keyboard: Option<widget::Id>,
31 pub widget_capturing_mouse: Option<widget::Id>,
33 pub widget_under_mouse: Option<widget::Id>,
38 pub modifiers: ModifierKey,
40}
41
42impl State {
43 pub fn new() -> State {
45 State {
46 touch: fnv::FnvHashMap::default(),
47 mouse: Mouse::new(),
48 widget_capturing_keyboard: None,
49 widget_capturing_mouse: None,
50 widget_under_mouse: None,
51 modifiers: ModifierKey::NO_MODIFIER,
52 }
53 }
54
55 pub fn relative_to(mut self, xy: Point) -> State {
57 self.mouse.xy = utils::vec2_sub(self.mouse.xy, xy);
58 self.mouse.buttons = self.mouse.buttons.relative_to(xy);
59 self
60 }
61}
62
63pub mod touch {
65 use position::Point;
66 use widget;
67
68 #[derive(Copy, Clone, Debug, PartialEq)]
70 pub struct Start {
71 pub time: instant::Instant,
73 pub xy: Point,
75 pub widget: Option<widget::Id>,
79 }
80
81 #[derive(Copy, Clone, Debug, PartialEq)]
83 pub struct Touch {
84 pub start: Start,
86 pub xy: Point,
88 pub widget: Option<widget::Id>,
90 }
91}
92
93pub mod mouse {
95 use position::Point;
96 use std;
97 use widget;
98
99 #[doc(inline)]
100 pub use input::MouseButton as Button;
101
102 pub const NUM_BUTTONS: usize = 9;
104
105 #[derive(Copy, Clone, Debug, PartialEq)]
107 pub struct Mouse {
108 pub buttons: ButtonMap,
113 pub xy: Point,
115 }
116
117 #[derive(Copy, Clone, Debug, PartialEq)]
119 pub enum ButtonPosition {
120 Up,
122 Down(Point, Option<widget::Id>),
125 }
126
127 #[derive(Copy, Clone, Debug, PartialEq)]
131 pub struct ButtonMap {
132 buttons: [ButtonPosition; NUM_BUTTONS],
133 }
134
135 #[derive(Clone)]
137 pub struct PressedButtons<'a> {
138 buttons: ::std::iter::Enumerate<::std::slice::Iter<'a, ButtonPosition>>,
139 }
140
141 impl Mouse {
142 pub fn new() -> Self {
144 Mouse {
145 buttons: ButtonMap::new(),
146 xy: [0.0, 0.0],
147 }
148 }
149 }
150
151 impl ButtonPosition {
152 pub fn relative_to(self, xy: Point) -> Self {
154 match self {
155 ButtonPosition::Down(pos, widget) => {
156 ButtonPosition::Down([pos[0] - xy[0], pos[1] - xy[1]], widget)
157 }
158 button_pos => button_pos,
159 }
160 }
161
162 pub fn is_down(&self) -> bool {
164 match *self {
165 ButtonPosition::Down(_, _) => true,
166 _ => false,
167 }
168 }
169
170 pub fn is_up(&self) -> bool {
172 match *self {
173 ButtonPosition::Up => true,
174 _ => false,
175 }
176 }
177
178 pub fn if_down(&self) -> Option<(Point, Option<widget::Id>)> {
181 match *self {
182 ButtonPosition::Down(xy, widget) => Some((xy, widget)),
183 _ => None,
184 }
185 }
186
187 pub fn xy_if_down(&self) -> Option<Point> {
189 match *self {
190 ButtonPosition::Down(xy, _) => Some(xy),
191 _ => None,
192 }
193 }
194 }
195
196 impl ButtonMap {
197 pub fn new() -> Self {
199 ButtonMap {
200 buttons: [ButtonPosition::Up; NUM_BUTTONS],
201 }
202 }
203
204 pub fn relative_to(self, xy: Point) -> Self {
206 self.buttons
207 .iter()
208 .enumerate()
209 .fold(ButtonMap::new(), |mut map, (idx, button_pos)| {
210 map.buttons[idx] = button_pos.relative_to(xy);
211 map
212 })
213 }
214
215 pub fn left(&self) -> &ButtonPosition {
217 &self[Button::Left]
218 }
219
220 pub fn middle(&self) -> &ButtonPosition {
222 &self[Button::Middle]
223 }
224
225 pub fn right(&self) -> &ButtonPosition {
227 &self[Button::Right]
228 }
229
230 pub fn press(&mut self, button: Button, xy: Point, widget: Option<widget::Id>) {
232 self.buttons[button_to_idx(button)] = ButtonPosition::Down(xy, widget);
233 }
234
235 pub fn release(&mut self, button: Button) {
237 self.buttons[button_to_idx(button)] = ButtonPosition::Up;
238 }
239
240 pub fn pressed(&self) -> PressedButtons {
243 PressedButtons {
244 buttons: self.buttons.iter().enumerate(),
245 }
246 }
247 }
248
249 fn button_to_idx(button: Button) -> usize {
251 let idx: u32 = button.into();
252 idx as usize
253 }
254
255 fn idx_to_button(idx: usize) -> Button {
257 (idx as u32).into()
258 }
259
260 impl std::ops::Index<Button> for ButtonMap {
261 type Output = ButtonPosition;
262 fn index(&self, button: Button) -> &Self::Output {
263 &self.buttons[button_to_idx(button)]
264 }
265 }
266
267 impl<'a> Iterator for PressedButtons<'a> {
268 type Item = (Button, Point, Option<widget::Id>);
269 fn next(&mut self) -> Option<Self::Item> {
270 while let Some((idx, button_pos)) = self.buttons.next() {
271 if let ButtonPosition::Down(xy, widget) = *button_pos {
272 return Some((idx_to_button(idx), xy, widget));
273 }
274 }
275 None
276 }
277 }
278}
279
280#[test]
281fn pressed_next_returns_none_if_no_buttons_are_pressed() {
282 let map = mouse::ButtonMap::new();
283 let pressed = map.pressed().next();
284 assert!(pressed.is_none());
285}
286
287#[test]
288fn pressed_next_should_return_first_pressed_button() {
289 let mut map = mouse::ButtonMap::new();
290
291 map.press(mouse::Button::Right, [3.0, 3.0], None);
292 map.press(mouse::Button::X1, [5.4, 4.5], None);
293
294 let pressed = map.pressed().next();
295 assert_eq!(Some((mouse::Button::Right, [3.0, 3.0], None)), pressed);
296}
297
298#[test]
299fn button_down_should_store_the_point() {
300 let mut map = mouse::ButtonMap::new();
301 let xy = [2.0, 5.0];
302 map.press(mouse::Button::Left, xy, None);
303
304 assert_eq!(
305 mouse::ButtonPosition::Down(xy, None),
306 map[mouse::Button::Left]
307 );
308}
309
310#[test]
311fn input_state_should_be_made_relative_to_a_given_point() {
312 let mut state = State::new();
313 state.mouse.xy = [50.0, -10.0];
314 state
315 .mouse
316 .buttons
317 .press(mouse::Button::Middle, [-20.0, -10.0], None);
318
319 let relative_state = state.relative_to([20.0, 20.0]);
320 assert_eq!([30.0, -30.0], relative_state.mouse.xy);
321 assert_eq!(
322 Some([-40.0, -30.0]),
323 relative_state.mouse.buttons[mouse::Button::Middle].xy_if_down()
324 );
325}