use std::{cell::RefCell, rc::Rc};
use cranpose_ui_graphics::{EdgeInsets, Point, Rect, Size};
use smallvec::SmallVec;
#[derive(Default)]
pub(crate) struct CoordinatorGeometry {
rects: RefCell<SmallVec<[Rect; 4]>>,
}
impl CoordinatorGeometry {
pub(crate) fn replace(&self, rects: impl IntoIterator<Item = Rect>) {
let mut stored = self.rects.borrow_mut();
stored.clear();
stored.extend(rects);
}
fn rect(&self, ordinal: usize) -> Option<Rect> {
self.rects.borrow().get(ordinal).copied()
}
}
#[derive(Clone, Default)]
pub(crate) struct CoordinatorRect {
geometry: Rc<CoordinatorGeometry>,
ordinal: usize,
padding: EdgeInsets,
}
impl CoordinatorRect {
pub(crate) fn new(
geometry: &Rc<CoordinatorGeometry>,
ordinal: usize,
padding: EdgeInsets,
) -> Self {
Self {
geometry: Rc::clone(geometry),
ordinal,
padding,
}
}
pub(crate) fn rect(&self, node_size: Size) -> Rect {
self.geometry
.rect(self.ordinal)
.unwrap_or_else(|| self.padding.inset_rect(node_size))
}
pub(crate) fn insets(&self, node_size: Size) -> EdgeInsets {
let rect = self.rect(node_size);
EdgeInsets {
left: rect.x,
top: rect.y,
right: node_size.width - rect.x - rect.width,
bottom: node_size.height - rect.y - rect.height,
}
}
pub(crate) fn origin(&self) -> Point {
self.geometry.rect(self.ordinal).map_or(
Point {
x: self.padding.left,
y: self.padding.top,
},
|rect| Point {
x: rect.x,
y: rect.y,
},
)
}
}
#[cfg(test)]
#[path = "tests/coordinator_geometry_tests.rs"]
mod tests;