notation_model/
lane_entry.rs

1use std::fmt::Display;
2use std::sync::{Arc, Weak};
3
4use crate::prelude::{BarLane, BarLaneProps, ModelEntry, Tab, TabBar, TabBarProps, Track};
5use notation_proto::prelude::{
6    BarPosition, Duration, Entry, EntryPassMode, ProtoEntry, TrackKind, Units, Slice,
7};
8
9#[derive(Clone, Debug, Default)]
10pub struct LaneEntryProps {
11    pub slice: Slice,
12    pub slice_index: usize,
13    pub index: usize,
14    pub in_bar_pos: Units,
15    pub tied_units: Units,
16    pub duration: Duration,
17}
18
19#[derive(Clone, Debug)]
20pub struct LaneEntry {
21    pub lane: Weak<BarLane>,
22    pub model: Arc<ModelEntry>,
23    pub props: LaneEntryProps,
24}
25impl Display for LaneEntry {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        write!(f, "<LaneEntry>({}: {})", self.props.index, self.model.proto)
28    }
29}
30impl LaneEntry {
31    pub fn new(
32        lane: Weak<BarLane>,
33        slice: Slice,
34        slice_index: usize,
35        index: usize,
36        model: Arc<ModelEntry>,
37        in_bar_pos: Units,
38    ) -> Self {
39        let props = LaneEntryProps {
40            slice,
41            slice_index,
42            index,
43            in_bar_pos,
44            tied_units: model.tied_units(),
45            duration: model.duration(),
46        };
47        Self { lane, model, props }
48    }
49}
50impl Entry for LaneEntry {
51    fn duration(&self) -> notation_proto::prelude::Duration {
52        self.model.duration()
53    }
54    fn prev_is_tie(&self) -> bool {
55        self.model.prev_is_tie()
56    }
57    fn next_is_tie(&self) -> bool {
58        self.model.next_is_tie()
59    }
60    fn tied_units(&self) -> Units {
61        self.model.tied_units()
62    }
63    fn pass_mode(&self) -> EntryPassMode {
64        self.model.pass_mode()
65    }
66}
67impl LaneEntry {
68    pub fn in_bar_pos(&self) -> Units {
69        self.props.in_bar_pos
70    }
71    pub fn bar_position(&self) -> BarPosition {
72        BarPosition::new(
73            self.bar_props().bar_units,
74            self.bar_props().bar_ordinal,
75            self.props.in_bar_pos,
76        )
77    }
78}
79impl LaneEntry {
80    pub fn lane(&self) -> Option<Arc<BarLane>> {
81        self.lane.upgrade().map(|x| x.clone())
82    }
83    pub fn track(&self) -> Option<Arc<Track>> {
84        self.lane().map(|x| x.track.clone())
85    }
86    pub fn bar(&self) -> Option<Arc<TabBar>> {
87        self.lane().and_then(|x| x.bar())
88    }
89    pub fn tab(&self) -> Option<Arc<Tab>> {
90        self.bar().and_then(|x| x.tab())
91    }
92    pub fn lane_props(&self) -> BarLaneProps {
93        self.lane().map(|x| x.props).unwrap_or_default()
94    }
95    pub fn bar_props(&self) -> TabBarProps {
96        self.bar().map(|x| x.props).unwrap_or_default()
97    }
98}
99impl LaneEntry {
100    pub fn model(&self) -> &ModelEntry {
101        self.model.as_ref()
102    }
103    pub fn proto(&self) -> &ProtoEntry {
104        self.model.proto.as_ref()
105    }
106    pub fn prev(&self) -> Option<Arc<LaneEntry>> {
107        if self.props.index == 0 {
108            None
109        } else if let Some(lane) = self.lane.upgrade() {
110            lane.entries.get(self.props.index - 1).map(|x| x.clone())
111        } else {
112            None
113        }
114    }
115    pub fn next(&self) -> Option<Arc<LaneEntry>> {
116        if let Some(lane) = self.lane.upgrade() {
117            lane.entries.get(self.props.index + 1).map(|x| x.clone())
118        } else {
119            None
120        }
121    }
122    pub fn prev_as_mark(&self) -> Option<String> {
123        if let Some(entry) = self.prev() {
124            entry.model.proto.as_mark().map(|x| x.clone())
125        } else {
126            None
127        }
128    }
129    pub fn track_id(&self) -> String {
130        self.model.track_id()
131    }
132    pub fn track_kind(&self) -> TrackKind {
133        self.model.track_kind()
134    }
135    pub fn track_index(&self) -> Option<usize> {
136        self.model.track_index()
137    }
138    pub fn get_lane_entry<T, F: Fn(&LaneEntry) -> Option<T>>(&self, predicate: &F) -> Option<T> {
139        if let Some(lane) = self.lane.upgrade() {
140            lane.get_entry(predicate)
141        } else {
142            None
143        }
144    }
145    pub fn get_track_entry<T, F: Fn(&ModelEntry) -> Option<T>>(&self, predicate: &F) -> Option<T> {
146        if let Some(lane) = self.lane.upgrade() {
147            lane.track.get_entry(predicate)
148        } else {
149            None
150        }
151    }
152}