use super::*;
pub trait Canvas: std::ops::Index<Pad, Output=Color> + std::ops::IndexMut<Pad, Output=Color> {
fn bounding_box_width(&self) -> u32;
fn bounding_box_height(&self) -> u32;
fn is_valid(&self, x: u32, y: u32) -> bool;
fn get_old_unchecked_ref(&self, x: u32, y: u32) -> &Color;
fn get_new_unchecked_ref(&self, x: u32, y: u32) -> &Color;
fn get_new_unchecked_mut(&mut self, x: u32, y: u32) -> &mut Color;
fn flush(&mut self) -> Result<(), crate::MidiError>;
fn lowest_visible_brightness(&self) -> f32;
fn get(&self, pad: Pad) -> Option<Color> {
if pad.x >= 0 && pad.y >= 0 && self.is_valid(pad.x as u32, pad.y as u32) {
Some(*self.get_old_unchecked_ref(pad.x as u32, pad.y as u32))
} else {
None
}
}
fn get_old_unchecked(&self, x: u32, y: u32) -> Color {
*self.get_old_unchecked_ref(x, y)
}
fn get_new_unchecked(&self, x: u32, y: u32) -> Color {
*self.get_new_unchecked_ref(x, y)
}
fn set_unchecked(&mut self, x: u32, y: u32, color: Color) {
*self.get_new_unchecked_mut(x, y) = color;
}
fn get_ref(&self, pad: Pad) -> Option<&Color> {
if pad.x >= 0 && pad.y >= 0 && self.is_valid(pad.x as u32, pad.y as u32) {
Some(self.get_old_unchecked_ref(pad.x as u32, pad.y as u32))
} else {
None
}
}
fn get_mut(&mut self, pad: Pad) -> Option<&mut Color> {
if pad.x >= 0 && pad.y >= 0 && self.is_valid(pad.x as u32, pad.y as u32) {
Some(self.get_new_unchecked_mut(pad.x as u32, pad.y as u32))
} else {
None
}
}
fn get_new(&self, pad: Pad) -> Option<Color> {
if pad.x >= 0 && pad.y >= 0 && self.is_valid(pad.x as u32, pad.y as u32) {
Some(*self.get_new_unchecked_ref(pad.x as u32, pad.y as u32))
} else {
None
}
}
fn at_new(&self, pad: Pad) -> Color {
self.get_new(pad).expect("Pad coordinates out of bounds")
}
#[must_use]
fn set(&mut self, pad: Pad, color: Color) -> Option<()> {
*self.get_mut(pad)? = color;
Some(())
}
fn iter(&self) -> CanvasIterator {
return CanvasIterator::new(self);
}
fn toggle(&mut self, pad: Pad, color: Color) -> Option<()> {
if self.get(pad)? == color {
self.set(pad, Color::BLACK)?;
} else {
self.set(pad, 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)
}
}
#[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 {
match self {
Self::Press { .. } => true,
_ => false,
}
}
pub fn is_release(&self) -> bool {
match self {
Self::Release { .. } => true,
_ => false,
}
}
}