use crate::*; #[derive(Debug, Clone)] pub struct MidiRangeModel { pub time_len: Arc, /// Length of visible time axis pub time_axis: Arc, /// Earliest time displayed pub time_start: Arc, /// Time step pub time_zoom: Arc, /// Auto rezoom to fit in time axis pub time_lock: Arc, /// Length of visible note axis pub note_axis: Arc, // Lowest note displayed pub note_lo: Arc, } from!(|data:(usize, bool)|MidiRangeModel = Self { time_len: Arc::new(0.into()), note_axis: Arc::new(0.into()), note_lo: Arc::new(0.into()), time_axis: Arc::new(0.into()), time_start: Arc::new(0.into()), time_zoom: Arc::new(data.0.into()), time_lock: Arc::new(data.1.into()), }); pub trait TimeRange { fn time_len (&self) -> &AtomicUsize; fn time_zoom (&self) -> &AtomicUsize; fn time_lock (&self) -> &AtomicBool; fn time_start (&self) -> &AtomicUsize; fn time_axis (&self) -> &AtomicUsize; fn time_end (&self) -> usize { self.time_start().get() + self.time_axis().get() * self.time_zoom().get() } } pub trait NoteRange { fn note_lo (&self) -> &AtomicUsize; fn note_axis (&self) -> &AtomicUsize; fn note_hi (&self) -> usize { (self.note_lo().get() + self.note_axis().get().saturating_sub(1)).min(127) } } pub trait MidiRange: TimeRange + NoteRange {} impl MidiRange for T {} impl TimeRange for MidiRangeModel { fn time_len (&self) -> &AtomicUsize { &self.time_len } fn time_zoom (&self) -> &AtomicUsize { &self.time_zoom } fn time_lock (&self) -> &AtomicBool { &self.time_lock } fn time_start (&self) -> &AtomicUsize { &self.time_start } fn time_axis (&self) -> &AtomicUsize { &self.time_axis } } impl NoteRange for MidiRangeModel { fn note_lo (&self) -> &AtomicUsize { &self.note_lo } fn note_axis (&self) -> &AtomicUsize { &self.note_axis } }