graphix_package_gui/widgets/
stack.rs1use 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}