use crate::*; /// /// ``` /// use tek::{TimeRange, NoteRange}; /// let model = tek::MidiSelection::from((1, false)); /// /// let _ = model.get_time_len(); /// let _ = model.get_time_zoom(); /// let _ = model.get_time_lock(); /// let _ = model.get_time_start(); /// let _ = model.get_time_axis(); /// let _ = model.get_time_end(); /// /// let _ = model.get_note_lo(); /// let _ = model.get_note_axis(); /// let _ = model.get_note_hi(); /// ``` #[derive(Debug, Clone, Default)] pub struct MidiSelection { 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, } pub trait MidiRange: TimeRange + NoteRange {} impl TimeRange for MidiEditor { fn time_len (&self) -> &AtomicUsize { self.mode.time_len() } fn time_zoom (&self) -> &AtomicUsize { self.mode.time_zoom() } fn time_lock (&self) -> &AtomicBool { self.mode.time_lock() } fn time_start (&self) -> &AtomicUsize { self.mode.time_start() } fn time_axis (&self) -> &AtomicUsize { self.mode.time_axis() } } impl NoteRange for MidiEditor { fn note_lo (&self) -> &AtomicUsize { self.mode.note_lo() } fn note_axis (&self) -> &AtomicUsize { self.mode.note_axis() } } impl_from!(MidiSelection: |data:(usize, bool)| 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()), }); impl TimeRange for MidiSelection { 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 MidiSelection { fn note_lo (&self) -> &AtomicUsize { &self.note_lo } fn note_axis (&self) -> &AtomicUsize { &self.note_axis } } pub trait TimeRange { fn time_len (&self) -> &AtomicUsize; fn get_time_len (&self) -> usize { self.time_len().load(Relaxed) } fn time_zoom (&self) -> &AtomicUsize; fn get_time_zoom (&self) -> usize { self.time_zoom().load(Relaxed) } fn set_time_zoom (&self, value: usize) -> usize { self.time_zoom().swap(value, Relaxed) } fn time_lock (&self) -> &AtomicBool; fn get_time_lock (&self) -> bool { self.time_lock().load(Relaxed) } fn set_time_lock (&self, value: bool) -> bool { self.time_lock().swap(value, Relaxed) } fn time_start (&self) -> &AtomicUsize; fn get_time_start (&self) -> usize { self.time_start().load(Relaxed) } fn set_time_start (&self, value: usize) -> usize { self.time_start().swap(value, Relaxed) } fn time_axis (&self) -> &AtomicUsize; fn get_time_axis (&self) -> usize { self.time_axis().load(Relaxed) } fn get_time_end (&self) -> usize { self.time_start().load(Relaxed) + self.time_axis().load(Relaxed) * self.time_zoom().load(Relaxed) } } pub trait NoteRange { fn note_lo (&self) -> &AtomicUsize; fn note_axis (&self) -> &AtomicUsize; fn get_note_lo (&self) -> usize { self.note_lo().load(Relaxed) } fn set_note_lo (&self, x: usize) -> usize { self.note_lo().swap(x, Relaxed) } fn get_note_axis (&self) -> usize { self.note_axis().load(Relaxed) } fn get_note_hi (&self) -> usize { (self.get_note_lo() + self.get_note_axis().saturating_sub(1)).min(127) } }