line_ui/element/
boxed.rs

1/*
2 * Copyright (c) 2025 Jasmine Tai. All rights reserved.
3 */
4
5use crate::element::Element;
6use crate::render::RenderChunk;
7
8/// An element with its type erased.
9///
10/// This type can be used to return multiple kinds of elements from a function.
11///
12/// # Example
13///
14/// ```
15/// use line_ui::element::{BoxElement, IntoElement};
16/// use line_ui::{Color, Style};
17///
18/// fn foo(value: bool) -> BoxElement<'static> {
19///     if value {
20///         "some fancy text"
21///             .fixed_width(20)
22///             .styled(Style::fg(Color::RED) + Style::INVERT)
23///             .boxed()
24///     } else {
25///         "just some text".boxed()
26///     }
27/// }
28/// ```
29pub struct BoxElement<'s> {
30    width: usize,
31    content: Vec<RenderChunk<'s>>,
32}
33
34impl<'s> BoxElement<'s> {
35    /// Boxes the provided element.
36    pub fn new<E: Element<'s>>(inner: E) -> Self {
37        let width = inner.width();
38        let content: Vec<_> = inner.render().collect();
39        debug_assert_eq!(width, content.iter().map(|chunk| chunk.width).sum());
40        BoxElement { width, content }
41    }
42}
43
44impl<'s> Element<'s> for BoxElement<'s> {
45    fn width(&self) -> usize {
46        self.width
47    }
48
49    fn render(&self) -> impl DoubleEndedIterator<Item = RenderChunk<'s>> {
50        self.content.iter().cloned()
51    }
52}