maycoon_widgets/
container.rs1use crate::ext::{WidgetChildrenExt, WidgetLayoutExt};
2use maycoon_core::app::info::AppInfo;
3use maycoon_core::app::update::Update;
4use maycoon_core::layout::{LayoutNode, LayoutStyle, StyleNode};
5use maycoon_core::state::{State, Val};
6use maycoon_core::vg::Scene;
7use maycoon_core::widget::Widget;
8use maycoon_theme::id::WidgetId;
9use maycoon_theme::theme::Theme;
10
11pub struct Container<S: State> {
20 style: Val<S, LayoutStyle>,
21 children: Vec<Val<S, Box<dyn Widget<S>>>>,
22}
23
24impl<S: State> Container<S> {
25 pub fn new(children: Vec<Val<S, Box<dyn Widget<S>>>>) -> Self {
27 Self {
28 style: LayoutStyle::default().into(),
29 children,
30 }
31 }
32
33 pub fn add_children(&mut self, children: Vec<Val<S, Box<dyn Widget<S>>>>) {
35 self.children.extend(children);
36 }
37
38 pub fn with_children(mut self, children: Vec<Val<S, Box<dyn Widget<S>>>>) -> Self {
40 self.add_children(children);
41 self
42 }
43
44 pub fn add_child(&mut self, child: impl Into<Val<S, Box<dyn Widget<S>>>>) {
46 self.children.push(child.into());
47 }
48
49 pub fn with_child(mut self, child: impl Into<Val<S, Box<dyn Widget<S>>>>) -> Self {
51 self.add_child(child);
52 self
53 }
54}
55
56impl<S: State> WidgetChildrenExt<S> for Container<S> {
57 fn set_children(&mut self, children: Vec<Val<S, impl Widget<S> + 'static>>) {
58 self.children = children
59 .into_iter()
60 .map(|val| val.map(|w| Box::new(w) as Box<dyn Widget<S> + 'static>))
61 .collect::<Vec<Val<S, Box<dyn Widget<S> + 'static>>>>();
62 }
63
64 fn add_child<W: Widget<S> + 'static>(&mut self, child: impl Into<Val<S, W>>) {
65 self.children.push(
66 child
67 .into()
68 .map(|w| Box::new(w) as Box<dyn Widget<S> + 'static>),
69 )
70 }
71}
72
73impl<S: State> WidgetLayoutExt<S> for Container<S> {
74 fn set_layout_style(&mut self, layout_style: impl Into<Val<S, LayoutStyle>>) {
75 self.style = layout_style.into();
76 }
77}
78
79impl<S: State> Default for Container<S> {
80 fn default() -> Self {
81 Self::new(Vec::new())
82 }
83}
84
85impl<S: State> Widget<S> for Container<S> {
86 fn render(
87 &mut self,
88 scene: &mut Scene,
89 theme: &mut dyn Theme,
90 info: &AppInfo,
91 layout_node: &LayoutNode,
92 state: &S,
93 ) {
94 for (i, child) in self.children.iter_mut().enumerate() {
95 let child = child.get_mut(state);
96 child.render(scene, theme, info, &layout_node.children[i], state);
97 }
98 }
99
100 fn layout_style(&mut self, state: &S) -> StyleNode {
101 let style = self.style.get_ref(state).clone();
102
103 let mut children = Vec::with_capacity(self.children.len());
104
105 for child in &mut self.children {
106 let child = child.get_mut(state);
107
108 children.push(child.layout_style(state));
109 }
110
111 StyleNode { style, children }
112 }
113
114 fn update(&mut self, layout: &LayoutNode, state: &mut S, info: &AppInfo) -> Update {
115 self.style.invalidate();
116
117 for child in &mut self.children {
118 child.invalidate();
119 }
120
121 let mut update = Update::empty();
122
123 for (i, child) in self.children.iter_mut().enumerate() {
124 let child = child.get_mut(state);
125 update.insert(child.update(&layout.children[i], state, info));
126 }
127
128 update
129 }
130
131 fn widget_id(&self) -> WidgetId {
132 WidgetId::new("maycoon-widgets", "Container")
133 }
134}