use std::hash::Hasher;
use stretch::result;
use crate::graphics::{Frame, Point};
use crate::ui::core::{self, Element, Event, Layout, MouseCursor};
pub struct Interface<'a, Message, Renderer> {
hash: u64,
root: Element<'a, Message, Renderer>,
layout: result::Layout,
}
pub struct Cache {
hash: u64,
layout: result::Layout,
}
impl<'a, Message, Renderer> Interface<'a, Message, Renderer>
where
Renderer: core::Renderer,
{
pub fn compute(
root: Element<'a, Message, Renderer>,
renderer: &Renderer,
) -> Interface<'a, Message, Renderer> {
let hasher = &mut twox_hash::XxHash::default();
root.hash(hasher);
let hash = hasher.finish();
let layout = root.compute_layout(renderer);
Interface { hash, root, layout }
}
pub fn compute_with_cache(
root: Element<'a, Message, Renderer>,
renderer: &Renderer,
cache: Cache,
) -> Interface<'a, Message, Renderer> {
let hasher = &mut twox_hash::XxHash::default();
root.hash(hasher);
let hash = hasher.finish();
let layout = if hash == cache.hash {
cache.layout
} else {
root.compute_layout(renderer)
};
Interface { hash, root, layout }
}
pub fn on_event(
&mut self,
event: Event,
cursor_position: Point,
messages: &mut Vec<Message>,
) {
let Interface { root, layout, .. } = self;
root.widget.on_event(
event,
Self::layout(layout),
cursor_position,
messages,
);
}
pub fn draw(
&self,
renderer: &mut Renderer,
frame: &mut Frame<'_>,
cursor_position: Point,
) -> MouseCursor {
let Interface { root, layout, .. } = self;
let cursor =
root.widget
.draw(renderer, Self::layout(layout), cursor_position);
renderer.flush(frame);
cursor
}
pub fn cache(self) -> Cache {
Cache {
hash: self.hash,
layout: self.layout,
}
}
fn layout(layout: &result::Layout) -> Layout<'_> {
Layout::new(layout, Point::new(0.0, 0.0))
}
}