use super::*;
pub trait Canvas:
std::ops::Index<Pad, Output = Color> + std::ops::IndexMut<Pad, Output = Color>
{
fn bounding_box(&self) -> (u32, u32);
fn low_level_get(&self, x: u32, y: u32) -> Option<&Color>;
fn low_level_get_pending(&self, x: u32, y: u32) -> Option<&Color>;
fn low_level_get_pending_mut(&mut self, x: u32, y: u32) -> Option<&mut Color>;
fn flush(&mut self) -> Result<(), crate::MidiError>;
fn lowest_visible_brightness(&self) -> f32;
fn get(&self, pad: Pad) -> Option<Color> {
let (x, y) = pad.to_u32()?;
self.low_level_get(x, y).copied()
}
fn get_pending(&self, pad: Pad) -> Option<Color> {
let (x, y) = pad.to_u32()?;
self.low_level_get_pending(x, y).copied()
}
fn set(&mut self, pad: Pad, color: Color) -> Option<()> {
let (x, y) = pad.to_u32()?;
*self.low_level_get_pending_mut(x, y)? = color;
Some(())
}
fn iter(&self) -> CanvasIterator {
CanvasIterator::new(self)
}
fn toggle(&mut self, pad: Pad, color: Color) -> Option<()> {
let (x, y) = pad.to_u32()?;
let current_color = self.low_level_get_pending_mut(x, y)?;
if *current_color == color {
*current_color = Color::BLACK;
} else {
*current_color = color;
}
Some(())
}
fn clear(&mut self)
where
Self: Sized,
{
for pad in self.iter() {
self[pad] = Color::BLACK;
}
}
fn into_padded(self) -> PaddingCanvas<Self>
where
Self: Sized,
{
PaddingCanvas::from(self)
}
fn is_valid(&self, pad: Pad) -> bool {
match pad.to_u32() {
Some((x, y)) => self.low_level_get(x, y).is_some(),
None => false,
}
}
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub enum CanvasMessage {
Press { x: u32, y: u32 },
Release { x: u32, y: u32 },
}
impl CanvasMessage {
pub fn x(&self) -> u32 {
match *self {
Self::Press { x, y: _ } => x,
Self::Release { x, y: _ } => x,
}
}
pub fn y(&self) -> u32 {
match *self {
Self::Press { x: _, y } => y,
Self::Release { x: _, y } => y,
}
}
pub fn pad(&self) -> Pad {
Pad {
x: self.x() as i32,
y: self.y() as i32,
}
}
pub fn is_press(&self) -> bool {
matches!(self, Self::Press { .. })
}
pub fn is_release(&self) -> bool {
matches!(self, Self::Release { .. })
}
}