Skip to main content

graphix_package_gui/widgets/
container.rs

1use super::{compile, GuiW, GuiWidget, IcedElement};
2use crate::types::{HAlignV, LengthV, PaddingV, VAlignV};
3use anyhow::{Context, Result};
4use arcstr::ArcStr;
5use graphix_compiler::expr::ExprId;
6use graphix_rt::{CallableId, GXExt, GXHandle, Ref, TRef};
7use iced_widget as widget;
8use netidx::publisher::Value;
9use tokio::try_join;
10
11pub(crate) struct ContainerW<X: GXExt> {
12    gx: GXHandle<X>,
13    padding: TRef<X, PaddingV>,
14    width: TRef<X, LengthV>,
15    height: TRef<X, LengthV>,
16    halign: TRef<X, HAlignV>,
17    valign: TRef<X, VAlignV>,
18    child_ref: Ref<X>,
19    child: GuiW<X>,
20}
21
22impl<X: GXExt> ContainerW<X> {
23    pub(crate) async fn compile(gx: GXHandle<X>, source: Value) -> Result<GuiW<X>> {
24        let [(_, child), (_, halign), (_, height), (_, padding), (_, valign), (_, width)] =
25            source.cast_to::<[(ArcStr, u64); 6]>().context("container flds")?;
26        let (child_ref, halign, height, padding, valign, width) = try_join! {
27            gx.compile_ref(child),
28            gx.compile_ref(halign),
29            gx.compile_ref(height),
30            gx.compile_ref(padding),
31            gx.compile_ref(valign),
32            gx.compile_ref(width),
33        }?;
34        let compiled_child = compile_child!(gx, child_ref, "container child");
35        Ok(Box::new(Self {
36            gx: gx.clone(),
37            padding: TRef::new(padding).context("container tref padding")?,
38            width: TRef::new(width).context("container tref width")?,
39            height: TRef::new(height).context("container tref height")?,
40            halign: TRef::new(halign).context("container tref halign")?,
41            valign: TRef::new(valign).context("container tref valign")?,
42            child_ref,
43            child: compiled_child,
44        }))
45    }
46}
47
48impl<X: GXExt> GuiWidget<X> for ContainerW<X> {
49    fn handle_update(
50        &mut self,
51        rt: &tokio::runtime::Handle,
52        id: ExprId,
53        v: &Value,
54    ) -> Result<bool> {
55        let mut changed = false;
56        changed |=
57            self.padding.update(id, v).context("container update padding")?.is_some();
58        changed |= self.width.update(id, v).context("container update width")?.is_some();
59        changed |=
60            self.height.update(id, v).context("container update height")?.is_some();
61        changed |=
62            self.halign.update(id, v).context("container update halign")?.is_some();
63        changed |=
64            self.valign.update(id, v).context("container update valign")?.is_some();
65        update_child!(self, rt, id, v, changed, child_ref, child, "container child recompile");
66        Ok(changed)
67    }
68
69    fn editor_action(
70        &mut self,
71        id: ExprId,
72        action: &iced_widget::text_editor::Action,
73    ) -> Option<(CallableId, Value)> {
74        self.child.editor_action(id, action)
75    }
76
77    fn view(&self) -> IcedElement<'_> {
78        let mut c = widget::Container::new(self.child.view());
79        if let Some(p) = self.padding.t.as_ref() {
80            c = c.padding(p.0);
81        }
82        if let Some(w) = self.width.t.as_ref() {
83            c = c.width(w.0);
84        }
85        if let Some(h) = self.height.t.as_ref() {
86            c = c.height(h.0);
87        }
88        if let Some(a) = self.halign.t.as_ref() {
89            c = c.align_x(a.0);
90        }
91        if let Some(a) = self.valign.t.as_ref() {
92            c = c.align_y(a.0);
93        }
94        c.into()
95    }
96}