graphix_package_gui/widgets/
qr_code.rs1use super::{GuiW, IcedElement};
2use anyhow::{Context, Result};
3use arcstr::ArcStr;
4use graphix_compiler::expr::ExprId;
5use graphix_rt::{GXExt, GXHandle, TRef};
6use iced_widget as widget;
7use log::error;
8use netidx::publisher::Value;
9use tokio::try_join;
10
11pub(crate) struct QrCodeW<X: GXExt> {
12 data: TRef<X, String>,
13 cell_size: TRef<X, Option<f64>>,
14 qr_data: Option<widget::qr_code::Data>,
15}
16
17impl<X: GXExt> QrCodeW<X> {
18 pub(crate) async fn compile(gx: GXHandle<X>, source: Value) -> Result<GuiW<X>> {
19 let [(_, cell_size), (_, data)] =
20 source.cast_to::<[(ArcStr, u64); 2]>().context("qr_code flds")?;
21 let (cell_size, data) = try_join! {
22 gx.compile_ref(cell_size),
23 gx.compile_ref(data),
24 }?;
25 let data = TRef::new(data).context("qr_code tref data")?;
26 let qr_data = data.t.as_deref().and_then(|s| match widget::qr_code::Data::new(s) {
27 Ok(d) => Some(d),
28 Err(e) => {
29 error!("qr_code: failed to encode data: {e}");
30 None
31 }
32 });
33 Ok(Box::new(Self {
34 data,
35 cell_size: TRef::new(cell_size).context("qr_code tref cell_size")?,
36 qr_data,
37 }))
38 }
39}
40
41impl<X: GXExt> super::GuiWidget<X> for QrCodeW<X> {
42 fn handle_update(
43 &mut self,
44 _rt: &tokio::runtime::Handle,
45 id: ExprId,
46 v: &Value,
47 ) -> Result<bool> {
48 let mut changed = false;
49 changed |=
50 self.cell_size.update(id, v).context("qr_code update cell_size")?.is_some();
51 if let Some(_) = self.data.update(id, v).context("qr_code update data")? {
52 self.qr_data = self.data.t.as_deref().and_then(
53 |s| match widget::qr_code::Data::new(s) {
54 Ok(d) => Some(d),
55 Err(e) => {
56 error!("qr_code: failed to encode data: {e}");
57 None
58 }
59 },
60 );
61 changed = true;
62 }
63 Ok(changed)
64 }
65
66 fn view(&self) -> IcedElement<'_> {
67 match &self.qr_data {
68 Some(data) => {
69 let mut qr = widget::QRCode::new(data);
70 if let Some(Some(sz)) = self.cell_size.t {
71 qr = qr.cell_size(sz as f32);
72 }
73 qr.into()
74 }
75 None => iced_widget::Space::new().into(),
76 }
77 }
78}