use std::cell::Ref;
use std::ops::Deref;
use platform_core::Event;
use renderer_core::DrawCommand;
use ui_core::{Component, ComponentList, EventResult};
use ui_tree::SegmentNodeInfo;
pub enum Frame<'a> {
Borrowed(Ref<'a, Vec<DrawCommand>>),
Owned(Vec<DrawCommand>),
}
impl Deref for Frame<'_> {
type Target = [DrawCommand];
fn deref(&self) -> &[DrawCommand] {
match self {
Frame::Borrowed(r) => r,
Frame::Owned(v) => v,
}
}
}
pub trait UiTree {
fn on_event(&mut self, event: &Event) -> EventResult;
fn frame(&self) -> Frame<'_>;
fn is_dirty(&self) -> bool;
fn generation(&self) -> u64;
fn walk(&self, out: &mut Vec<SegmentNodeInfo>);
fn bump_force_ticks(&self) {}
}
pub struct LocalTree(ComponentList);
impl LocalTree {
pub fn new(root: Box<dyn Component>) -> Self {
Self(ComponentList::new(root))
}
}
impl UiTree for LocalTree {
fn on_event(&mut self, event: &Event) -> EventResult {
self.0.on_event(event)
}
fn frame(&self) -> Frame<'_> {
Frame::Borrowed(self.0.commands())
}
fn is_dirty(&self) -> bool {
self.0.is_dirty()
}
fn generation(&self) -> u64 {
self.0.generation()
}
fn walk(&self, out: &mut Vec<SegmentNodeInfo>) {
self.0.walk_tree(out);
}
fn bump_force_ticks(&self) {
self.0.bump_force_ticks();
}
}
pub struct HotTree {
tree: ComponentList,
}
impl HotTree {
pub fn mount(app: &dyn crate::app::App) -> *mut HotTree {
Box::into_raw(Box::new(HotTree {
tree: ComponentList::new(app.root()),
}))
}
pub unsafe fn release(ptr: *mut HotTree) {
drop(unsafe { Box::from_raw(ptr) });
}
pub unsafe fn on_event(ptr: *mut HotTree, event: &Event) -> bool {
let this = unsafe { &mut *ptr };
this.tree.on_event(event) == EventResult::Handled
}
pub unsafe fn paint(ptr: *mut HotTree) -> Vec<DrawCommand> {
let this = unsafe { &*ptr };
this.tree.commands().clone()
}
pub unsafe fn is_dirty(ptr: *mut HotTree) -> bool {
let this = unsafe { &*ptr };
this.tree.is_dirty()
}
pub unsafe fn generation(ptr: *mut HotTree) -> u64 {
let this = unsafe { &*ptr };
this.tree.generation()
}
pub unsafe fn walk(ptr: *mut HotTree) -> Vec<SegmentNodeInfo> {
let this = unsafe { &*ptr };
let mut out = Vec::new();
this.tree.walk_tree(&mut out);
out
}
}
pub struct TreeView<'a>(pub &'a dyn UiTree);
impl devtools_core::DevTreeView for TreeView<'_> {
fn node_count(&self) -> usize {
let mut nodes = Vec::new();
self.0.walk(&mut nodes);
nodes.len()
}
fn for_each_node(&self, f: &mut dyn FnMut(&devtools_core::DevNodeInfo)) {
let mut nodes = Vec::new();
self.0.walk(&mut nodes);
for node in &nodes {
f(&devtools_core::DevNodeInfo {
id: node.id,
name: node.name,
rect: node.rect,
depth: node.depth,
});
}
}
}