use std::any::Any;
use std::rc::Rc;
use crate::draw::DrawCtx;
use crate::graph::{NodeId, NodeKind, SceneGraph, with_graph};
use crate::handles::Node;
pub type SizeFn = Rc<dyn Fn() -> (f64, f64)>;
pub trait Draw: 'static {
fn draw(&self, ctx: &mut DrawCtx);
fn size(&self) -> (f64, f64) {
(100.0, 100.0)
}
}
#[doc(hidden)]
pub fn add<T: Draw>(
graph: &SceneGraph,
parent: NodeId,
base: crate::BaseProps,
type_name: &'static str,
snapshot: Rc<dyn Fn() -> T>,
state: Rc<dyn Any>,
) -> NodeId {
let paint = snapshot.clone();
let measure = snapshot;
let kind = NodeKind::Custom {
draw: Rc::new(move |ctx: &mut DrawCtx, _| paint().draw(ctx)),
width: 0.0,
height: 0.0,
measure: Some(Rc::new(move || measure().size())),
state: Some(state),
type_name,
};
crate::builder::insert(graph, parent, kind, base)
}
#[doc(hidden)]
pub fn state<S: 'static>(node: Node) -> Rc<S> {
with_graph(|g| match &g.node(node.id()).kind {
NodeKind::Custom {
state: Some(s),
type_name,
..
} => s
.clone()
.downcast::<S>()
.unwrap_or_else(|_| panic!("{type_name} node has state of another type")),
_ => panic!("this handle does not point to a derived node"),
})
}