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}