use crate::{
Cache, Clipboard, Command, Debug, Event, Program, Renderer, Size,
UserInterface,
};
#[allow(missing_debug_implementations)]
pub struct State
where
P: Program + 'static,
{
program: P,
cache: Option,
primitive: ::Output,
queued_events: Vec,
queued_messages: Vec,
}
impl State
where
P: Program + 'static,
{
pub fn new(
mut program: P,
bounds: Size,
renderer: &mut P::Renderer,
debug: &mut Debug,
) -> Self {
let user_interface = build_user_interface(
&mut program,
Cache::default(),
renderer,
bounds,
debug,
);
debug.draw_started();
let primitive = user_interface.draw(renderer);
debug.draw_finished();
let cache = Some(user_interface.into_cache());
State {
program,
cache,
primitive,
queued_events: Vec::new(),
queued_messages: Vec::new(),
}
}
pub fn program(&self) -> &P {
&self.program
}
pub fn primitive(&self) -> &::Output {
&self.primitive
}
pub fn queue_event(&mut self, event: Event) {
self.queued_events.push(event);
}
pub fn queue_message(&mut self, message: P::Message) {
self.queued_messages.push(message);
}
pub fn update(
&mut self,
clipboard: Option<&dyn Clipboard>,
bounds: Size,
renderer: &mut P::Renderer,
debug: &mut Debug,
) -> Option> {
if self.queued_events.is_empty() && self.queued_messages.is_empty() {
return None;
}
let mut user_interface = build_user_interface(
&mut self.program,
self.cache.take().unwrap(),
renderer,
bounds,
debug,
);
debug.event_processing_started();
let mut messages = user_interface.update(
self.queued_events.drain(..),
clipboard,
renderer,
);
messages.extend(self.queued_messages.drain(..));
debug.event_processing_finished();
if messages.is_empty() {
debug.draw_started();
self.primitive = user_interface.draw(renderer);
debug.draw_finished();
self.cache = Some(user_interface.into_cache());
None
} else {
// When there are messages, we are forced to rebuild twice
// for now :^)
let temp_cache = user_interface.into_cache();
let commands =
Command::batch(messages.into_iter().map(|message| {
debug.log_message(&message);
debug.update_started();
let command = self.program.update(message);
debug.update_finished();
command
}));
let user_interface = build_user_interface(
&mut self.program,
temp_cache,
renderer,
bounds,
debug,
);
debug.draw_started();
self.primitive = user_interface.draw(renderer);
debug.draw_finished();
self.cache = Some(user_interface.into_cache());
Some(commands)
}
}
}
fn build_user_interface<'a, P: Program>(
program: &'a mut P,
cache: Cache,
renderer: &mut P::Renderer,
size: Size,
debug: &mut Debug,
) -> UserInterface<'a, P::Message, P::Renderer> {
debug.view_started();
let view = program.view();
debug.view_finished();
debug.layout_started();
let user_interface = UserInterface::build(view, size, cache, renderer);
debug.layout_finished();
user_interface
}