fission_core/ui/widgets/
builder.rs1use crate::{AppState, BuildCtx, BoxConstraints, Node, NodeId, View, Widget, WidgetNodeId};
2use crate::ui::Container;
3use std::sync::Arc;
4
5pub struct Builder<S: AppState> {
17 builder: Arc<dyn Fn(&mut BuildCtx<S>, &View<S>) -> Node + Send + Sync>,
18}
19
20impl<S: AppState> Builder<S> {
21 pub fn new<F>(builder: F) -> Self
22 where
23 F: Fn(&mut BuildCtx<S>, &View<S>) -> Node + Send + Sync + 'static,
24 {
25 Self {
26 builder: Arc::new(builder),
27 }
28 }
29}
30
31impl<S: AppState> Widget<S> for Builder<S> {
32 fn build(&self, ctx: &mut BuildCtx<S>, view: &View<S>) -> Node {
33 (self.builder)(ctx, view)
34 }
35}
36
37pub struct LayoutBuilder<S: AppState> {
53 pub id: Option<WidgetNodeId>,
55 pub flex_grow: f32,
57 pub flex_shrink: f32,
59 builder: Arc<dyn Fn(&mut BuildCtx<S>, &View<S>, BoxConstraints) -> Node + Send + Sync>,
60}
61
62impl<S: AppState> LayoutBuilder<S> {
63 pub fn new<F>(builder: F) -> Self
64 where
65 F: Fn(&mut BuildCtx<S>, &View<S>, BoxConstraints) -> Node + Send + Sync + 'static,
66 {
67 Self {
68 id: None,
69 flex_grow: 0.0,
70 flex_shrink: 1.0,
71 builder: Arc::new(builder),
72 }
73 }
74
75 pub fn id(mut self, id: WidgetNodeId) -> Self {
76 self.id = Some(id);
77 self
78 }
79
80 pub fn flex_grow(mut self, grow: f32) -> Self {
81 self.flex_grow = grow;
82 self
83 }
84
85 pub fn flex_shrink(mut self, shrink: f32) -> Self {
86 self.flex_shrink = shrink;
87 self
88 }
89}
90
91impl<S: AppState> Widget<S> for LayoutBuilder<S> {
92 fn build(&self, ctx: &mut BuildCtx<S>, view: &View<S>) -> Node {
93 let viewport = view
94 .layout
95 .map(|layout| layout.viewport_size)
96 .unwrap_or_else(|| view.viewport_size());
97 let mut max_w = viewport.width;
98 let mut max_h = viewport.height;
99 if !max_w.is_finite() || max_w <= 0.0 {
100 max_w = f32::INFINITY;
101 }
102 if !max_h.is_finite() || max_h <= 0.0 {
103 max_h = f32::INFINITY;
104 }
105 let fallback = BoxConstraints::loose(max_w, max_h);
106 let constraints = self
107 .id
108 .and_then(|id| view.get_constraints(id))
109 .unwrap_or(fallback);
110 let child = (self.builder)(ctx, view, constraints);
111 if let Some(id) = self.id {
112 Container::new(child)
113 .id(NodeId::from(id))
114 .flex_grow(self.flex_grow)
115 .flex_shrink(self.flex_shrink)
116 .into_node()
117 } else {
118 child
119 }
120 }
121}