use crate::{
common::ToOpenTimelineType, components::TimelineSubtimelineGui, config::SharedConfig,
impl_is_valid_method_for_iterable, impl_valid_asynchronous_macro_never_called,
};
use eframe::egui::{Context, Ui};
use open_timeline_core::{IsReducedCollection, ReducedTimelines};
use open_timeline_gui_core::{
Draw, ShowRemoveButton, Valid, ValidSynchronous, ValidityAsynchronous, ValiditySynchronous,
};
use std::sync::Arc;
#[derive(Debug)]
pub struct TimelineSubtimelinesGui {
subtimelines: Vec<TimelineSubtimelineGui>,
shared_config: SharedConfig,
}
impl TimelineSubtimelinesGui {
pub fn new(shared_config: SharedConfig) -> Self {
Self {
subtimelines: vec![],
shared_config,
}
}
pub fn add_empty_subtimeline(&mut self) {
self.subtimelines.push(TimelineSubtimelineGui::new(
Arc::clone(&self.shared_config),
ShowRemoveButton::Yes,
));
}
pub fn from_reduced_timelines(
shared_config: SharedConfig,
orginal_timelines: Option<ReducedTimelines>,
) -> Self {
let timelines = match orginal_timelines.clone() {
None => Vec::new(),
Some(timelines) => timelines
.into_iter()
.map(|timeline| {
TimelineSubtimelineGui::from_reduced_timeline(
Arc::clone(&shared_config),
ShowRemoveButton::Yes,
timeline,
)
})
.collect(),
};
Self {
subtimelines: timelines,
shared_config,
}
}
}
impl ToOpenTimelineType<Option<ReducedTimelines>> for TimelineSubtimelinesGui {
fn to_opentimeline_type(&self) -> Option<ReducedTimelines> {
let mut subtimelines = ReducedTimelines::new();
for subtimeline in &self.subtimelines {
let subtimeline = subtimeline.to_opentimeline_type();
subtimelines.collection_mut().insert(subtimeline);
}
(!subtimelines.collection().is_empty()).then_some(subtimelines)
}
}
impl ValidSynchronous for TimelineSubtimelinesGui {
fn is_valid_synchronous(&self) -> bool {
self.subtimelines
.iter()
.all(|subtimeline| subtimeline.is_valid_synchronous())
}
fn update_validity_synchronous(&mut self) {
self.subtimelines
.iter_mut()
.for_each(|subtimeline| subtimeline.update_validity_synchronous())
}
fn validity_synchronous(&self) -> ValiditySynchronous {
for subtimeline in &self.subtimelines {
match subtimeline.validity_synchronous() {
ValiditySynchronous::Invalid(error) => return ValiditySynchronous::Invalid(error),
ValiditySynchronous::Valid => continue,
}
}
ValiditySynchronous::Valid
}
}
impl_valid_asynchronous_macro_never_called!(TimelineSubtimelinesGui);
impl Valid for TimelineSubtimelinesGui {
fn validity(&self) -> ValidityAsynchronous {
let validity: Vec<ValidityAsynchronous> = self
.subtimelines
.iter()
.map(|subtimeline| subtimeline.validity())
.collect();
impl_is_valid_method_for_iterable!(validity)
}
fn update_validity(&mut self) {
panic!()
}
}
impl Draw for TimelineSubtimelinesGui {
fn draw(&mut self, ctx: &Context, ui: &mut Ui) {
open_timeline_gui_core::Label::sub_heading(ui, "Subtimelines");
if self.subtimelines.is_empty() {
open_timeline_gui_core::Label::none(ui);
} else {
for subtimeline in &mut self.subtimelines {
subtimeline.draw(ctx, ui);
}
self.subtimelines
.retain(|subtimeline| !subtimeline.to_be_removed());
}
ui.add_space(5.0);
if open_timeline_gui_core::Button::add(ui).clicked() {
self.add_empty_subtimeline();
}
}
}