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