Skip to main content

graphix_package_gui/widgets/
text_input.rs

1use super::{GuiW, GuiWidget, IcedElement, Message};
2use crate::types::{FontV, LengthV, PaddingV};
3use anyhow::{Context, Result};
4use arcstr::ArcStr;
5use graphix_compiler::expr::ExprId;
6use graphix_rt::{Callable, GXExt, GXHandle, Ref, TRef};
7use iced_widget as widget;
8use netidx::{protocol::valarray::ValArray, publisher::Value};
9use tokio::try_join;
10
11pub(crate) struct TextInputW<X: GXExt> {
12    gx: GXHandle<X>,
13    disabled: TRef<X, bool>,
14    value: TRef<X, String>,
15    placeholder: TRef<X, String>,
16    on_input: Ref<X>,
17    on_input_callable: Option<Callable<X>>,
18    on_submit: Ref<X>,
19    on_submit_callable: Option<Callable<X>>,
20    is_secure: TRef<X, bool>,
21    width: TRef<X, LengthV>,
22    padding: TRef<X, PaddingV>,
23    size: TRef<X, Option<f64>>,
24    font: TRef<X, Option<FontV>>,
25}
26
27impl<X: GXExt> TextInputW<X> {
28    pub(crate) async fn compile(gx: GXHandle<X>, source: Value) -> Result<GuiW<X>> {
29        let [(_, disabled), (_, font), (_, is_secure), (_, on_input), (_, on_submit), (_, padding), (_, placeholder), (_, size), (_, value), (_, width)] =
30            source.cast_to::<[(ArcStr, u64); 10]>().context("text_input flds")?;
31        let (
32            disabled,
33            font,
34            is_secure,
35            on_input,
36            on_submit,
37            padding,
38            placeholder,
39            size,
40            value,
41            width,
42        ) = try_join! {
43            gx.compile_ref(disabled),
44            gx.compile_ref(font),
45            gx.compile_ref(is_secure),
46            gx.compile_ref(on_input),
47            gx.compile_ref(on_submit),
48            gx.compile_ref(padding),
49            gx.compile_ref(placeholder),
50            gx.compile_ref(size),
51            gx.compile_ref(value),
52            gx.compile_ref(width),
53        }?;
54        let on_input_callable =
55            compile_callable!(gx, on_input, "text_input on_input");
56        let on_submit_callable =
57            compile_callable!(gx, on_submit, "text_input on_submit");
58        Ok(Box::new(Self {
59            gx: gx.clone(),
60            disabled: TRef::new(disabled).context("text_input tref disabled")?,
61            value: TRef::new(value).context("text_input tref value")?,
62            placeholder: TRef::new(placeholder).context("text_input tref placeholder")?,
63            on_input,
64            on_input_callable,
65            on_submit,
66            on_submit_callable,
67            is_secure: TRef::new(is_secure).context("text_input tref is_secure")?,
68            width: TRef::new(width).context("text_input tref width")?,
69            padding: TRef::new(padding).context("text_input tref padding")?,
70            size: TRef::new(size).context("text_input tref size")?,
71            font: TRef::new(font).context("text_input tref font")?,
72        }))
73    }
74}
75
76impl<X: GXExt> GuiWidget<X> for TextInputW<X> {
77    fn handle_update(
78        &mut self,
79        rt: &tokio::runtime::Handle,
80        id: ExprId,
81        v: &Value,
82    ) -> Result<bool> {
83        let mut changed = false;
84        changed |=
85            self.disabled.update(id, v).context("text_input update disabled")?.is_some();
86        changed |= self.value.update(id, v).context("text_input update value")?.is_some();
87        changed |= self
88            .placeholder
89            .update(id, v)
90            .context("text_input update placeholder")?
91            .is_some();
92        changed |= self
93            .is_secure
94            .update(id, v)
95            .context("text_input update is_secure")?
96            .is_some();
97        changed |= self.width.update(id, v).context("text_input update width")?.is_some();
98        changed |=
99            self.padding.update(id, v).context("text_input update padding")?.is_some();
100        changed |= self.size.update(id, v).context("text_input update size")?.is_some();
101        changed |= self.font.update(id, v).context("text_input update font")?.is_some();
102        update_callable!(self, rt, id, v, on_input, on_input_callable, "text_input on_input recompile");
103        update_callable!(self, rt, id, v, on_submit, on_submit_callable, "text_input on_submit recompile");
104        Ok(changed)
105    }
106
107    fn view(&self) -> IcedElement<'_> {
108        let val = self.value.t.as_deref().unwrap_or("");
109        let placeholder = self.placeholder.t.as_deref().unwrap_or("");
110        let mut ti = widget::TextInput::new(placeholder, val);
111        if !self.disabled.t.unwrap_or(false) {
112            if let Some(callable) = &self.on_input_callable {
113                let id = callable.id();
114                ti = ti.on_input(move |s| {
115                    Message::Call(id, ValArray::from_iter([Value::String(s.into())]))
116                });
117            }
118            if let Some(callable) = &self.on_submit_callable {
119                ti = ti.on_submit(Message::Call(
120                    callable.id(),
121                    ValArray::from_iter([Value::Null]),
122                ));
123            }
124        }
125        if self.is_secure.t == Some(true) {
126            ti = ti.secure(true);
127        }
128        if let Some(w) = self.width.t.as_ref() {
129            ti = ti.width(w.0);
130        }
131        if let Some(p) = self.padding.t.as_ref() {
132            ti = ti.padding(p.0);
133        }
134        if let Some(Some(sz)) = self.size.t {
135            ti = ti.size(sz as f32);
136        }
137        if let Some(Some(f)) = self.font.t.as_ref() {
138            ti = ti.font(f.0);
139        }
140        ti.into()
141    }
142}