streamdeck_oxide/view/
matrix.rs

1//! Button matrix for the view system.
2//!
3//! This module provides a matrix of buttons for the view system.
4
5use generic_array::{sequence::GenericSequence, ArrayLength, GenericArray};
6use std::marker::PhantomData;
7
8use super::button::Button;
9
10/// A matrix of buttons.
11///
12/// This struct represents a matrix of buttons in the view system.
13/// It is parameterized by the width and height of the matrix.
14pub struct ButtonMatrix<W, H>
15where
16    W: ArrayLength,
17    H: ArrayLength,
18{
19    /// The buttons in the matrix.
20    pub(crate) buttons: GenericArray<GenericArray<Button, W>, H>,
21    /// Phantom data for the width.
22    pub(crate) _width: PhantomData<W>,
23    /// Phantom data for the height.
24    pub(crate) _height: PhantomData<H>,
25}
26
27impl<W, H> Default for ButtonMatrix<W, H>
28where
29    W: ArrayLength,
30    H: ArrayLength,
31{
32    fn default() -> Self {
33        ButtonMatrix {
34            buttons: GenericArray::generate(|_| GenericArray::generate(|_| Button::default())),
35            _width: PhantomData,
36            _height: PhantomData,
37        }
38    }
39}
40
41impl<W, H> ButtonMatrix<W, H>
42where
43    W: ArrayLength,
44    H: ArrayLength,
45{
46    /// Create a new button matrix.
47    pub fn new() -> Self {
48        ButtonMatrix::default()
49    }
50
51    /// Get a button by index.
52    ///
53    /// This method returns a reference to the button at the given index.
54    /// The index is calculated as `y * width + x`.
55    pub fn get_button_by_index(&self, index: usize) -> Option<&Button> {
56        if index < W::to_usize() * H::to_usize() {
57            let x = index % W::to_usize();
58            let y = index / W::to_usize();
59            Some(&self.buttons[y][x])
60        } else {
61            None
62        }
63    }
64
65    /// Get a button by coordinates.
66    ///
67    /// This method returns a reference to the button at the given coordinates.
68    pub fn get_button(&self, x: usize, y: usize) -> Option<&Button> {
69        if x < W::to_usize() && y < H::to_usize() {
70            Some(&self.buttons[y][x])
71        } else {
72            None
73        }
74    }
75
76    /// Set a button by coordinates.
77    ///
78    /// This method sets the button at the given coordinates.
79    pub fn set_button(
80        &mut self,
81        x: usize,
82        y: usize,
83        button: Button,
84    ) -> Result<(), Box<dyn std::error::Error>> {
85        if x < W::to_usize() && y < H::to_usize() {
86            self.buttons[y][x] = button;
87            Ok(())
88        } else {
89            Err(Box::new(std::io::Error::new(
90                std::io::ErrorKind::InvalidInput,
91                "Button index out of bounds",
92            )))
93        }
94    }
95
96    /// Set a button by index.
97    ///
98    /// This method sets the button at the given index.
99    /// The index is calculated as `y * width + x`.
100    pub fn set_button_by_index(
101        &mut self,
102        index: usize,
103        button: Button,
104    ) -> Result<(), Box<dyn std::error::Error>> {
105        if index < W::to_usize() * H::to_usize() {
106            let x = index % W::to_usize();
107            let y = index / W::to_usize();
108            self.buttons[y][x] = button;
109            Ok(())
110        } else {
111            Err(Box::new(std::io::Error::new(
112                std::io::ErrorKind::InvalidInput,
113                "Button index out of bounds",
114            )))
115        }
116    }
117
118    /// Get the width of the matrix.
119    pub fn width(&self) -> usize {
120        W::to_usize()
121    }
122
123    /// Get the height of the matrix.
124    pub fn height(&self) -> usize {
125        H::to_usize()
126    }
127
128    /// Get the total number of buttons in the matrix.
129    pub fn size(&self) -> usize {
130        W::to_usize() * H::to_usize()
131    }
132}