Skip to main content

graphix_package_gui/widgets/
stack.rs

1use super::{compile_children, GuiW, GuiWidget, IcedElement};
2use crate::types::LengthV;
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 StackW<X: GXExt> {
12    gx: GXHandle<X>,
13    children_ref: Ref<X>,
14    children: Vec<GuiW<X>>,
15    width: TRef<X, LengthV>,
16    height: TRef<X, LengthV>,
17}
18
19impl<X: GXExt> StackW<X> {
20    pub(crate) async fn compile(gx: GXHandle<X>, source: Value) -> Result<GuiW<X>> {
21        let [(_, children), (_, height), (_, width)] =
22            source.cast_to::<[(ArcStr, u64); 3]>().context("stack flds")?;
23        let (children_ref, height, width) = try_join! {
24            gx.compile_ref(children),
25            gx.compile_ref(height),
26            gx.compile_ref(width),
27        }?;
28        let compiled_children = match children_ref.last.as_ref() {
29            None => vec![],
30            Some(v) => {
31                compile_children(gx.clone(), v.clone()).await.context("stack children")?
32            }
33        };
34        Ok(Box::new(Self {
35            gx: gx.clone(),
36            children_ref,
37            children: compiled_children,
38            width: TRef::new(width).context("stack tref width")?,
39            height: TRef::new(height).context("stack tref height")?,
40        }))
41    }
42}
43
44impl<X: GXExt> GuiWidget<X> for StackW<X> {
45    fn handle_update(
46        &mut self,
47        rt: &tokio::runtime::Handle,
48        id: ExprId,
49        v: &Value,
50    ) -> Result<bool> {
51        let mut changed = false;
52        changed |= self.width.update(id, v).context("stack update width")?.is_some();
53        changed |= self.height.update(id, v).context("stack update height")?.is_some();
54        if id == self.children_ref.id {
55            self.children_ref.last = Some(v.clone());
56            self.children = rt
57                .block_on(compile_children(self.gx.clone(), v.clone()))
58                .context("stack children recompile")?;
59            changed = true;
60        }
61        for child in &mut self.children {
62            changed |= child.handle_update(rt, id, v)?;
63        }
64        Ok(changed)
65    }
66
67    fn editor_action(
68        &mut self,
69        id: ExprId,
70        action: &iced_widget::text_editor::Action,
71    ) -> Option<(CallableId, Value)> {
72        for child in &mut self.children {
73            if let some @ Some(_) = child.editor_action(id, action) {
74                return some;
75            }
76        }
77        None
78    }
79
80    fn view(&self) -> IcedElement<'_> {
81        let mut s = widget::Stack::new();
82        if let Some(w) = self.width.t.as_ref() {
83            s = s.width(w.0);
84        }
85        if let Some(h) = self.height.t.as_ref() {
86            s = s.height(h.0);
87        }
88        for child in &self.children {
89            s = s.push(child.view());
90        }
91        s.into()
92    }
93}