Skip to main content

notation_model/
bar_lane.rs

1use std::fmt::Display;
2use std::sync::{Arc, Weak};
3
4use notation_proto::prelude::Units;
5
6use crate::prelude::{LaneEntry, LaneKind, Slice, Tab, TabBar, TabBarProps, Track, TrackProps, LaneEntryProps};
7
8#[derive(Copy, Clone, Debug, Default)]
9pub struct BarLaneProps {
10    pub index: usize,
11    pub track: TrackProps,
12}
13
14#[derive(Clone, Debug)]
15pub struct BarLane {
16    pub bar: Weak<TabBar>,
17    pub kind: LaneKind,
18    pub track: Arc<Track>,
19    pub entries: Vec<Arc<LaneEntry>>,
20    pub props: BarLaneProps,
21}
22impl Display for BarLane {
23    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24        write!(
25            f,
26            "<BarLane>({} E:{})",
27            self.id(),
28            self.entries.len()
29        )
30    }
31}
32
33impl BarLane {
34    pub fn id(&self) -> String {
35        self.kind_id(self.kind)
36    }
37    pub fn kind_id(&self, kind: LaneKind) -> String {
38        format!("{}:{}", self.track.id, kind)
39    }
40    pub fn order(&self) -> (usize, LaneKind) {
41        (self.track.props.index, self.kind)
42    }
43    pub fn try_new_arc(
44        bar: Weak<TabBar>,
45        index: usize,
46        track: &Arc<Track>,
47        slice: Slice,
48    ) -> Option<Arc<Self>> {
49        let model_entries = track.get_entries(&slice.begin, &slice.end);
50        let kind = LaneKind::of_entries(&track.kind, &model_entries);
51        if !kind.is_none() {
52            Some(Arc::<Self>::new_cyclic(|weak_self| {
53                let props = BarLaneProps {
54                    index,
55                    track: track.props,
56                };
57                let entries = LaneEntry::new_entries(model_entries, weak_self, slice);
58                Self {
59                    bar,
60                    kind,
61                    track: track.clone(),
62                    entries,
63                    props,
64                }
65            }))
66        } else {
67            None
68        }
69    }
70    pub fn merge_lane(&self, lane: &BarLane) -> Arc<Self> {
71        Arc::<Self>::new_cyclic(|weak_self| {
72            let mut entries = Vec::new();
73            for entry in self.entries.iter() {
74                entries.push(entry.clone());
75            }
76            for entry in lane.entries.iter() {
77                entries.push(entry.clone());
78            }
79            entries.sort_by(|a, b| {
80                a.props.in_bar_pos.cmp(&b.props.in_bar_pos)
81            });
82            let entries = entries.iter().enumerate().map(|(index, entry)| {
83                let merged_entry = LaneEntry {
84                    props: LaneEntryProps {
85                        slice: entry.props.slice.clone(),
86                        index,
87                        ..entry.props
88                    },
89                    lane: weak_self.clone(),
90                    model: entry.model.clone(),
91                };
92                Arc::new(merged_entry)
93            }).collect();
94            Self {
95                bar: self.bar.clone(),
96                kind: self.kind,
97                track: self.track.clone(),
98                entries,
99                props: self.props,
100            }
101        })
102    }
103    pub fn bar(&self) -> Option<Arc<TabBar>> {
104        self.bar.upgrade().map(|x| x.clone())
105    }
106    pub fn tab(&self) -> Option<Arc<Tab>> {
107        self.bar().and_then(|x| x.tab())
108    }
109    pub fn bar_props(&self) -> TabBarProps {
110        self.bar().map(|x| x.props).unwrap_or_default()
111    }
112    pub fn get_entry_at<T, F: Fn(&LaneEntry) -> Option<T>>(
113        &self,
114        in_bar_pos: Units,
115        predicate: &F,
116    ) -> Option<T> {
117        for entry in self.entries.iter() {
118            if in_bar_pos < entry.props.in_bar_pos {
119                break;
120            } else {
121                if in_bar_pos < entry.props.in_bar_pos + entry.model().props.tied_units {
122                    if let Some(result) = predicate(entry.as_ref()) {
123                        return Some(result);
124                    }
125                }
126            }
127        }
128        None
129    }
130    pub fn get_next_entry<T, F: Fn(&LaneEntry) -> Option<T>>(
131        &self,
132        in_bar_pos: Units,
133        predicate: &F,
134    ) -> Option<T> {
135        self.get_entry(&|x: &LaneEntry| {
136            if x.props.in_bar_pos.is_bigger_than(&in_bar_pos) {
137                predicate(x)
138            } else {
139                None
140            }
141        })
142    }
143}