notation_model 0.6.0

Fun notation - runtime models
Documentation
use std::fmt::Display;
use std::sync::{Arc, Weak};

use crate::prelude::{BarLane, BarLaneProps, ModelEntry, Tab, TabBar, TabBarProps, Track};
use notation_proto::prelude::{
    BarPosition, Duration, Entry, EntryPassMode, ProtoEntry, TrackKind, Units, Slice,
};

#[derive(Clone, Debug, Default)]
pub struct LaneEntryProps {
    pub slice: Slice,
    pub slice_index: usize,
    pub index: usize,
    pub in_bar_pos: Units,
    pub tied_units: Units,
    pub duration: Duration,
}

#[derive(Clone, Debug)]
pub struct LaneEntry {
    pub lane: Weak<BarLane>,
    pub model: Arc<ModelEntry>,
    pub props: LaneEntryProps,
}
impl Display for LaneEntry {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "<LaneEntry>({}: {})", self.props.index, self.model.proto)
    }
}
impl LaneEntry {
    pub fn new(
        lane: Weak<BarLane>,
        slice: Slice,
        slice_index: usize,
        index: usize,
        model: Arc<ModelEntry>,
        in_bar_pos: Units,
    ) -> Self {
        let props = LaneEntryProps {
            slice,
            slice_index,
            index,
            in_bar_pos,
            tied_units: model.tied_units(),
            duration: model.duration(),
        };
        Self { lane, model, props }
    }
}
impl Entry for LaneEntry {
    fn duration(&self) -> notation_proto::prelude::Duration {
        self.model.duration()
    }
    fn prev_is_tie(&self) -> bool {
        self.model.prev_is_tie()
    }
    fn next_is_tie(&self) -> bool {
        self.model.next_is_tie()
    }
    fn tied_units(&self) -> Units {
        self.model.tied_units()
    }
    fn pass_mode(&self) -> EntryPassMode {
        self.model.pass_mode()
    }
}
impl LaneEntry {
    pub fn in_bar_pos(&self) -> Units {
        self.props.in_bar_pos
    }
    pub fn bar_position(&self) -> BarPosition {
        BarPosition::new(
            self.bar_props().bar_units,
            self.bar_props().bar_ordinal,
            self.props.in_bar_pos,
        )
    }
}
impl LaneEntry {
    pub fn lane(&self) -> Option<Arc<BarLane>> {
        self.lane.upgrade().map(|x| x.clone())
    }
    pub fn track(&self) -> Option<Arc<Track>> {
        self.lane().map(|x| x.track.clone())
    }
    pub fn bar(&self) -> Option<Arc<TabBar>> {
        self.lane().and_then(|x| x.bar())
    }
    pub fn tab(&self) -> Option<Arc<Tab>> {
        self.bar().and_then(|x| x.tab())
    }
    pub fn lane_props(&self) -> BarLaneProps {
        self.lane().map(|x| x.props).unwrap_or_default()
    }
    pub fn bar_props(&self) -> TabBarProps {
        self.bar().map(|x| x.props).unwrap_or_default()
    }
}
impl LaneEntry {
    pub fn model(&self) -> &ModelEntry {
        self.model.as_ref()
    }
    pub fn proto(&self) -> &ProtoEntry {
        self.model.proto.as_ref()
    }
    pub fn prev(&self) -> Option<Arc<LaneEntry>> {
        if self.props.index == 0 {
            None
        } else if let Some(lane) = self.lane.upgrade() {
            lane.entries.get(self.props.index - 1).map(|x| x.clone())
        } else {
            None
        }
    }
    pub fn next(&self) -> Option<Arc<LaneEntry>> {
        if let Some(lane) = self.lane.upgrade() {
            lane.entries.get(self.props.index + 1).map(|x| x.clone())
        } else {
            None
        }
    }
    pub fn prev_as_mark(&self) -> Option<String> {
        if let Some(entry) = self.prev() {
            entry.model.proto.as_mark().map(|x| x.clone())
        } else {
            None
        }
    }
    pub fn track_id(&self) -> String {
        self.model.track_id()
    }
    pub fn track_kind(&self) -> TrackKind {
        self.model.track_kind()
    }
    pub fn track_index(&self) -> Option<usize> {
        self.model.track_index()
    }
    pub fn get_lane_entry<T, F: Fn(&LaneEntry) -> Option<T>>(&self, predicate: &F) -> Option<T> {
        if let Some(lane) = self.lane.upgrade() {
            lane.get_entry(predicate)
        } else {
            None
        }
    }
    pub fn get_track_entry<T, F: Fn(&ModelEntry) -> Option<T>>(&self, predicate: &F) -> Option<T> {
        if let Some(lane) = self.lane.upgrade() {
            lane.track.get_entry(predicate)
        } else {
            None
        }
    }
}