fission_core/ui/widgets/
builder.rs1use crate::build::{self, BuildCtxHandle, ViewHandle};
2use crate::ui::{Container, Widget};
3use crate::{BoxConstraints, GlobalState, WidgetId};
4use std::sync::Arc;
5
6#[derive(Clone)]
13pub struct Builder<S: GlobalState> {
14 builder: Arc<dyn Fn(BuildCtxHandle<S>, ViewHandle<S>) -> Widget + Send + Sync>,
15}
16
17impl<S: GlobalState> Builder<S> {
18 pub fn new<F>(builder: F) -> Self
19 where
20 F: Fn(BuildCtxHandle<S>, ViewHandle<S>) -> Widget + Send + Sync + 'static,
21 {
22 Self {
23 builder: Arc::new(builder),
24 }
25 }
26}
27
28impl<S: GlobalState> From<Builder<S>> for Widget {
29 fn from(component: Builder<S>) -> Self {
30 let (ctx, view) = build::current::<S>();
31 (component.builder)(ctx, view)
32 }
33}
34
35#[derive(Clone)]
42pub struct LayoutBuilder<S: GlobalState> {
43 pub id: Option<WidgetId>,
45 pub flex_grow: f32,
47 pub flex_shrink: f32,
49 builder: Arc<dyn Fn(BuildCtxHandle<S>, ViewHandle<S>, BoxConstraints) -> Widget + Send + Sync>,
50}
51
52impl<S: GlobalState> LayoutBuilder<S> {
53 pub fn new<F>(builder: F) -> Self
54 where
55 F: Fn(BuildCtxHandle<S>, ViewHandle<S>, BoxConstraints) -> Widget + Send + Sync + 'static,
56 {
57 Self {
58 id: None,
59 flex_grow: 0.0,
60 flex_shrink: 1.0,
61 builder: Arc::new(builder),
62 }
63 }
64
65 pub fn flex_grow(mut self, grow: f32) -> Self {
66 self.flex_grow = grow;
67 self
68 }
69
70 pub fn flex_shrink(mut self, shrink: f32) -> Self {
71 self.flex_shrink = shrink;
72 self
73 }
74}
75
76impl<S: GlobalState> From<LayoutBuilder<S>> for Widget {
77 fn from(component: LayoutBuilder<S>) -> Self {
78 let (ctx, view) = build::current::<S>();
79 let viewport = view.viewport_size();
80 let mut max_w = viewport.width;
81 let mut max_h = viewport.height;
82 if !max_w.is_finite() || max_w <= 0.0 {
83 max_w = f32::INFINITY;
84 }
85 if !max_h.is_finite() || max_h <= 0.0 {
86 max_h = f32::INFINITY;
87 }
88 let fallback = BoxConstraints::loose(max_w, max_h);
89 let id = build::current_widget_id().or(component.id);
90 let constraints = id
91 .and_then(|id| view.get_constraints(id))
92 .unwrap_or(fallback);
93 let child = (component.builder)(ctx, view, constraints);
94
95 if let Some(id) = id {
96 let mut container = Container::new(child)
97 .flex_grow(component.flex_grow)
98 .flex_shrink(component.flex_shrink);
99 container.id = Some(id);
100 container.into()
101 } else {
102 child
103 }
104 }
105}