use crate::core::FrameArena;
use crate::view::context::ElementContext;
use crate::view::element::Element;
use std::cell::{Cell, RefCell};
use std::ptr::NonNull;
use taffy::NodeId;
thread_local! {
static ARENA: RefCell<FrameArena> = RefCell::new(FrameArena::new());
static LIVE_ELEMENTS: Cell<usize> = const { Cell::new(0) };
}
pub struct AnyElement {
pointer: NonNull<dyn Element>,
}
impl AnyElement {
pub fn new<E: Element>(element: E) -> Self {
let pointer = ARENA.with(|arena| {
let allocated: *mut E = arena.borrow().alloc(element);
allocated as *mut dyn Element
});
LIVE_ELEMENTS.with(|live| live.set(live.get() + 1));
Self { pointer: unsafe { NonNull::new_unchecked(pointer) } }
}
fn element(&mut self) -> &mut dyn Element {
unsafe { self.pointer.as_mut() }
}
pub fn request_layout(&mut self, cx: &mut ElementContext) -> NodeId {
self.element().request_layout(cx)
}
pub fn prepaint(&mut self, cx: &mut ElementContext) {
self.element().prepaint(cx);
}
pub fn paint(&mut self, cx: &mut ElementContext) {
self.element().paint(cx);
}
pub fn z_index(&mut self) -> i16 {
self.element().z_index()
}
}
impl Drop for AnyElement {
fn drop(&mut self) {
unsafe { std::ptr::drop_in_place(self.pointer.as_ptr()) };
LIVE_ELEMENTS.with(|live| live.set(live.get().saturating_sub(1)));
}
}
pub fn reset_frame_arena() {
if LIVE_ELEMENTS.with(Cell::get) == 0 {
ARENA.with(|arena| arena.borrow_mut().reset());
}
}