1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MouseButton {
    Left,
    Right,
    Middle,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MouseEventType {
    Down(MouseButton),
    Up(MouseButton),
    Move,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MouseEvent {
    pub etype: MouseEventType,
    pub pos: (u32, u32),
}

#[derive(Copy, Clone, Default, PartialEq, Eq)]
pub struct MouseState {
    pub buttons: [bool; 3],
    pub pos: (u32, u32),
}

impl MouseEvent {
    pub fn new(etype: MouseEventType, pos: (u32, u32)) -> Self {
        Self {
            etype,
            pos,
        }
    }
}

impl From<usize> for MouseButton {
    fn from(index: usize) -> MouseButton {
        match index {
            0 => MouseButton::Left,
            1 => MouseButton::Right,
            2 => MouseButton::Middle,
            _ => panic!("unexpected mouse button index: {:?}", index),
        }
    }
}

impl From<MouseButton> for usize {
    fn from(button: MouseButton) -> usize {
        match button {
            MouseButton::Left => 0,
            MouseButton::Right => 1,
            MouseButton::Middle => 2,
        }
    }
}

impl MouseState {
    pub fn with(left: bool, right: bool, middle: bool, x: u32, y: u32) -> Self {
        Self {
            buttons: [left, right, middle],
            pos: (x, y),
        }
    }

    pub fn to_events(&mut self, next_state: MouseState) -> Vec<MouseEvent> {
        if *self != next_state {
            self.pos = next_state.pos;

            let events: Vec<MouseEvent> = self
                .buttons
                .into_iter()
                .zip(next_state.buttons)
                .enumerate()
                .filter_map(|(i, (prev, next))| {
                    if prev != next {
                        self.buttons[i] = next;
                        let button = MouseButton::from(i);
                        let etype = if next {
                            MouseEventType::Down(button)
                        } else {
                            MouseEventType::Up(button)
                        };
                        Some(MouseEvent::new(etype, next_state.pos))
                    } else {
                        None
                    }
                })
                .collect();

            if !events.is_empty() {
                events
            } else {
                vec![MouseEvent::new(MouseEventType::Move, next_state.pos)]
            }
        } else {
            vec![]
        }
    }

    pub fn update_with(&mut self, event: MouseEvent) {
        self.pos = event.pos;
        match event.etype {
            MouseEventType::Up(button) => self.buttons[usize::from(button)] = false,
            MouseEventType::Down(button) => self.buttons[usize::from(button)] = true,
            MouseEventType::Move => {},
        }
    }
}