use std::cell::Cell;
use std::rc::Rc;
use ratatui_core::layout::Rect;
use crate::geometry::Size;
use crate::surface::Surface;
use crate::view::{Element, RenderCtx, ScopedElement, View, element};
#[derive(Clone, Debug, Default)]
pub struct RectProbe(Rc<Cell<Rect>>);
impl RectProbe {
pub fn new() -> Self {
Self::default()
}
pub fn rect(&self) -> Rect {
self.0.get()
}
pub fn wrap<'view, V: View + 'view>(&self, view: V) -> ScopedElement<'view> {
element(Probe::new(view, self))
}
fn set(&self, rect: Rect) {
self.0.set(rect);
}
}
pub struct Probe<V: View = Element> {
inner: V,
probe: RectProbe,
}
impl<V: View> Probe<V> {
pub fn new(inner: V, probe: &RectProbe) -> Self {
Self {
inner,
probe: probe.clone(),
}
}
}
impl<V: View> View for Probe<V> {
fn measure(&self, available: Size, ctx: &RenderCtx) -> Size {
self.inner.measure(available, ctx)
}
fn render(&self, area: Rect, surface: &mut Surface, ctx: &RenderCtx) {
self.probe.set(area);
self.inner.render(area, surface, ctx);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::components::{Flex, Text};
use crate::style::Theme;
use crate::view::element;
use ratatui_core::layout::Rect;
#[test]
fn probe_reports_the_rect_a_view_was_painted_into() {
let probe = RectProbe::new();
assert_eq!(probe.rect(), Rect::ZERO, "an unpainted probe reads ZERO");
let root = Flex::column()
.fixed(1, element(Text::raw("header")))
.grow(1, probe.wrap(element(Text::raw("body"))));
let theme = Theme::default();
let _ = crate::testing::render(&root, 10, 5, &theme);
assert_eq!(probe.rect(), Rect::new(0, 1, 10, 4));
}
}