use super::{
Delegate,
ApplicationContext,
KeyManager,
MouseState,
SpawnableDelegate,
SpawnHandle,
};
use dmsort;
use graphics::Graphics;
use raii_counter::WeakCounter;
use std::cmp;
mod spawner;
pub use self::spawner::DelegateSpawner;
pub struct DelegateManager {
spawner: DelegateSpawner,
root_delegates: Vec<Box<Delegate>>,
delegates: Vec<SpawnedDelegate>,
}
struct SpawnedDelegate {
inner: Box<Delegate>,
handles_counter: WeakCounter,
}
impl DelegateManager {
pub(in application) fn as_spawner(&mut self) -> &mut DelegateSpawner {
&mut self.spawner
}
pub(in application) fn new() -> DelegateManager {
DelegateManager {
spawner: DelegateSpawner::new(),
root_delegates: Vec::new(),
delegates: Vec::new(),
}
}
pub(in application) fn tick(
&mut self,
context: &mut ApplicationContext,
key_manager: &KeyManager,
mouse_state: &MouseState,
graphics: &mut Graphics,
) {
self.delegates.retain(|d| d.handles_counter.count() > 0);
{
let mut root_delegates_index = 0;
let mut delegates_index = 0;
loop {
if root_delegates_index >= self.root_delegates.len() {
for index in delegates_index..self.delegates.len() {
self.delegates[index].inner.tick(context, key_manager, mouse_state, &mut self.spawner);
self.delegates[index].inner.render(graphics);
}
break;
} else if delegates_index >= self.delegates.len() {
for index in root_delegates_index..self.root_delegates.len() {
self.root_delegates[index].tick(context, key_manager, mouse_state, &mut self.spawner);
self.root_delegates[index].render(graphics);
}
break;
} else {
let order = cmp::min(
self.root_delegates[root_delegates_index].render_order(),
self.delegates[delegates_index].inner.render_order(),
);
for index in delegates_index..self.delegates.len() {
if self.delegates[index].inner.render_order() != order {
break;
}
self.delegates[index].inner.tick(context, key_manager, mouse_state, &mut self.spawner);
self.delegates[index].inner.render(graphics);
delegates_index += 1;
}
for index in root_delegates_index..self.root_delegates.len() {
if self.root_delegates[index].render_order() != order {
break;
}
self.root_delegates[index].tick(context, key_manager, mouse_state, &mut self.spawner);
self.root_delegates[index].render(graphics);
root_delegates_index += 1;
}
}
}
}
self.collect_from_spawner();
}
fn collect_from_spawner(&mut self) {
let prev_root_len = self.root_delegates.len();
let prev_delegates_len = self.delegates.len();
for root_delegate in self.spawner.spawned_root_delegates() {
self.root_delegates.push(root_delegate);
}
for delegate in self.spawner.spawned_delegates() {
self.delegates.push(delegate);
}
if prev_root_len != self.root_delegates.len() {
dmsort::sort_by_key(&mut self.root_delegates, |d| d.render_order());
}
if prev_delegates_len != self.delegates.len() {
dmsort::sort_by_key(&mut self.delegates, |d| d.inner.render_order());
}
}
}