use ratatui_core::layout::Rect;
use crate::geometry::Size;
use crate::surface::Surface;
use crate::view::{Element, RenderCtx, View};
pub struct FocusScope {
focused: bool,
child: Element,
}
impl FocusScope {
pub fn new(focused: bool, child: Element) -> Self {
Self { focused, child }
}
pub fn focused(child: Element) -> Self {
Self::new(true, child)
}
pub fn unfocused(child: Element) -> Self {
Self::new(false, child)
}
}
impl View for FocusScope {
fn measure(&self, available: Size) -> Size {
self.child.measure(available)
}
fn render(&self, area: Rect, surface: &mut Surface, ctx: &RenderCtx) {
self.child
.render(area, surface, &ctx.with_focus(self.focused));
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Surface;
use crate::components::{Boxed, Text};
use crate::test_support::{buffer, rainbow_theme};
use crate::view::{RenderCtx, element};
fn corner_color(scope_focused: bool, root_focused: bool) -> ratatui_core::style::Color {
let t = rainbow_theme();
let mut buf = buffer(8, 3);
let area = buf.area;
let ctx = RenderCtx::new(&t).with_focus(root_focused);
let view = FocusScope::new(scope_focused, element(Boxed::new(element(Text::raw("x")))));
let mut surface = Surface::new(&mut buf, area);
view.render(area, &mut surface, &ctx);
buf[(0, 0)].fg
}
#[test]
fn focus_scope_overrides_root_focus_for_its_subtree() {
let t = rainbow_theme();
assert_eq!(corner_color(true, false), t.border_focused);
assert_eq!(corner_color(false, true), t.border);
}
#[test]
fn focus_scope_is_layout_transparent() {
let inner = Boxed::new(element(Text::raw("hello")));
let want = inner.measure(Size::new(40, 10));
let scoped = FocusScope::focused(element(Boxed::new(element(Text::raw("hello")))));
assert_eq!(scoped.measure(Size::new(40, 10)), want);
}
}