use std::any::Any;
use crate::{
channel::Channel,
execution::{AnyHandler, Handler, TaskExecutor},
task::{AnyTask, TaskData},
};
pub trait TasksCollection<'c> {
type Context: 'c;
type Target: Send + 'static;
type Executor: TaskExecutor + Default;
fn name() -> &'static str;
fn handle(context: Self::Context) -> Handler<'c, Self::Target>;
}
pub struct CollectionData {
name: &'static str,
channel: Channel<Box<dyn Any + Send>>,
tasks: Vec<TaskData>,
executor: Box<dyn TaskExecutor>,
}
impl CollectionData {
#[cfg(feature = "egui")]
pub fn ui(&self, ui: &mut egui::Ui) {
ui.collapsing(self.name, |ui| {
for task in &self.tasks {
ui.group(|ui| task.ui(ui));
}
});
}
pub fn name(&self) -> &str {
self.name
}
pub(super) fn from_collection<'c, C>() -> Self
where
C: TasksCollection<'c>,
C::Executor: 'static,
{
Self {
name: C::name(),
channel: Channel::new(),
tasks: Vec::new(),
executor: Box::<C::Executor>::default(),
}
}
fn execute(&mut self, task: AnyTask) {
let sender = self.channel.sender();
let task_data = task.execute(sender);
self.push_task_data(task_data);
}
fn push_task_data(&mut self, task_data: TaskData) {
self.tasks.push(task_data)
}
pub(crate) fn push_task(&mut self, task: AnyTask) {
self.executor.push(task);
}
pub fn handle_all(&mut self, result_handle: AnyHandler<'_>) {
self.handle_execution();
self.handle_progress();
self.handle_results(result_handle);
self.handle_deletion();
}
pub fn handle_results(&mut self, mut handle: AnyHandler<'_>) {
if let Ok(value) = self.channel.receiver().try_recv() {
handle.apply(value)
}
}
pub fn handle_deletion(&mut self) {
self.tasks.retain(|task| !task.is_finished())
}
pub fn handle_progress(&mut self) {
for progress in self.tasks.iter_mut().filter_map(|task| task.progress_mut()) {
if let Ok(data) = progress.receiver().try_recv() {
data.apply(progress.current_mut())
}
}
}
pub fn handle_execution(&mut self) {
use crate::execution::ExecutionPoll as E;
while let E::Ready(task) = self.executor.poll(&self.tasks) {
self.execute(task)
}
}
}