pixel_widgets/widget/
frame.rs

1use crate::draw::Primitive;
2use crate::layout::{Rectangle, Size};
3use crate::node::{IntoNode, Node};
4use crate::style::Stylesheet;
5use crate::widget::*;
6
7/// A widget that wraps around a content widget
8pub struct Frame<'a, T> {
9    content: Option<Node<'a, T>>,
10}
11
12impl<'a, T: 'a> Frame<'a, T> {
13    /// Construct a new `Frame` with content
14    pub fn new(content: impl IntoNode<'a, T>) -> Self {
15        Self {
16            content: Some(content.into_node()),
17        }
18    }
19
20    /// Sets the content widget from the first element of an iterator.
21    pub fn extend<I: IntoIterator<Item = N>, N: IntoNode<'a, T>>(mut self, iter: I) -> Self {
22        if self.content.is_none() {
23            self.content = iter.into_iter().next().map(IntoNode::into_node);
24        }
25        self
26    }
27
28    fn content(&self) -> &Node<'a, T> {
29        self.content.as_ref().expect("content of `Frame` must be set")
30    }
31
32    fn content_mut(&mut self) -> &mut Node<'a, T> {
33        self.content.as_mut().expect("content of `Frame` must be set")
34    }
35}
36
37impl<'a, T: 'a> Default for Frame<'a, T> {
38    fn default() -> Self {
39        Self { content: None }
40    }
41}
42
43impl<'a, T: 'a> Widget<'a, T> for Frame<'a, T> {
44    type State = ();
45
46    fn mount(&self) {}
47
48    fn widget(&self) -> &'static str {
49        "frame"
50    }
51
52    fn len(&self) -> usize {
53        1
54    }
55
56    fn visit_children(&mut self, visitor: &mut dyn FnMut(&mut dyn GenericNode<'a, T>)) {
57        visitor(&mut **self.content_mut());
58    }
59
60    fn size(&self, _: &(), style: &Stylesheet) -> (Size, Size) {
61        style
62            .background
63            .resolve_size((style.width, style.height), self.content().size(), style.padding)
64    }
65
66    fn event(
67        &mut self,
68        _: &mut (),
69        layout: Rectangle,
70        clip: Rectangle,
71        style: &Stylesheet,
72        event: Event,
73        context: &mut Context<T>,
74    ) {
75        self.content_mut().event(
76            style.background.content_rect(layout, style.padding),
77            clip,
78            event,
79            context,
80        );
81    }
82
83    fn draw(&mut self, _: &mut (), layout: Rectangle, clip: Rectangle, style: &Stylesheet) -> Vec<Primitive<'a>> {
84        let content_rect = style.background.content_rect(layout, style.padding);
85
86        style
87            .background
88            .render(layout)
89            .into_iter()
90            .chain(self.content_mut().draw(content_rect, clip).into_iter())
91            .collect()
92    }
93}
94
95impl<'a, T: 'a> IntoNode<'a, T> for Frame<'a, T> {
96    fn into_node(self) -> Node<'a, T> {
97        Node::from_widget(self)
98    }
99}