notation_model 0.6.0

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

use crate::prelude::{Tab, Track};
use notation_proto::prelude::{
    Duration, Entry, EntryPassMode, FrettedEntry4, FrettedEntry6, ProtoEntry, TrackKind, Units,
};

#[derive(Copy, Clone, Debug)]
pub struct ModelEntryProps {
    pub index: usize,
    pub tied_units: Units,
}

#[derive(Debug)]
pub struct ModelEntry {
    pub track: Weak<Track>,
    pub proto: Arc<ProtoEntry>,
    pub props: ModelEntryProps,
}
impl ModelEntry {
    pub fn new(
        track: Weak<Track>,
        proto: Arc<ProtoEntry>,
        index: usize,
        tied_units: Units,
    ) -> Self {
        let props = ModelEntryProps { index, tied_units };
        Self {
            track,
            proto,
            props,
        }
    }
}
impl Entry for ModelEntry {
    fn duration(&self) -> notation_proto::prelude::Duration {
        self.proto.duration()
    }
    fn prev_is_tie(&self) -> bool {
        self.prev().map(|x| x.proto.is_core_tie()).unwrap_or(false)
    }
    fn next_is_tie(&self) -> bool {
        self.next().map(|x| x.proto.is_core_tie()).unwrap_or(false)
    }
    fn tied_units(&self) -> Units {
        self.props.tied_units
    }
    fn pass_mode(&self) -> EntryPassMode {
        self.proto.pass_mode()
    }
}
impl ModelEntry {
    pub fn track(&self) -> Option<Arc<Track>> {
        self.track.upgrade().map(|x| x.clone())
    }
    pub fn tab(&self) -> Option<Arc<Tab>> {
        self.track().and_then(|x| x.tab())
    }
    pub fn as_fretted6(&self) -> Option<&FrettedEntry6> {
        self.proto.as_fretted6()
    }
    pub fn as_fretted4(&self) -> Option<&FrettedEntry4> {
        self.proto.as_fretted4()
    }
    pub fn prev(&self) -> Option<Arc<ModelEntry>> {
        if self.props.index == 0 {
            None
        } else if let Some(track) = self.track.upgrade() {
            track.entries.get(self.props.index - 1).map(|x| x.clone())
        } else {
            None
        }
    }
    pub fn next(&self) -> Option<Arc<ModelEntry>> {
        if let Some(track) = self.track.upgrade() {
            track.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.proto.as_mark().map(|x| x.clone())
        } else {
            None
        }
    }
    pub fn get_tied_prev(&self) -> Option<Arc<ModelEntry>> {
        if self.props.index <= 1 {
            return None;
        }
        if let Some(track) = self.track.upgrade() {
            if let Some(prev) = track.entries.get(self.props.index - 1) {
                if prev.proto.is_core_tie() {
                    for i in self.props.index - 2..=0 {
                        let entry = track.entries.get(i).unwrap();
                        if entry.duration() != Duration::Zero {
                            return Some(entry.clone());
                        }
                    }
                }
            }
        }
        None
    }
    pub fn get_tied_next(&self) -> Option<Arc<ModelEntry>> {
        if let Some(track) = self.track.upgrade() {
            if let Some(next) = track.entries.get(self.props.index + 1) {
                if next.proto.is_core_tie() {
                    for i in self.props.index + 2..track.entries.len() {
                        let entry = track.entries.get(i).unwrap();
                        if entry.duration() != Duration::Zero {
                            return Some(entry.clone());
                        }
                    }
                }
            }
        }
        None
    }
    pub fn track_id(&self) -> String {
        if let Some(track) = self.track.upgrade() {
            track.id.clone()
        } else {
            "".to_owned()
        }
    }
    pub fn track_kind(&self) -> TrackKind {
        if let Some(track) = self.track.upgrade() {
            track.kind.clone()
        } else {
            TrackKind::Unsupported
        }
    }
    pub fn track_index(&self) -> Option<usize> {
        if let Some(track) = self.track.upgrade() {
            Some(track.props.index)
        } else {
            None
        }
    }
    pub fn get_track_entry<T, F: Fn(&ModelEntry) -> Option<T>>(&self, predicate: &F) -> Option<T> {
        if let Some(track) = self.track.upgrade() {
            track.get_entry(predicate)
        } else {
            None
        }
    }
}