Skip to main content

graphix_package_gui/widgets/
qr_code.rs

1use 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 =
27            data.t.as_deref().and_then(|s| match widget::qr_code::Data::new(s) {
28                Ok(d) => Some(d),
29                Err(e) => {
30                    error!("qr_code: failed to encode data: {e}");
31                    None
32                }
33            });
34        Ok(Box::new(Self {
35            data,
36            cell_size: TRef::new(cell_size).context("qr_code tref cell_size")?,
37            qr_data,
38        }))
39    }
40}
41
42impl<X: GXExt> super::GuiWidget<X> for QrCodeW<X> {
43    fn handle_update(
44        &mut self,
45        _rt: &tokio::runtime::Handle,
46        id: ExprId,
47        v: &Value,
48    ) -> Result<bool> {
49        let mut changed = false;
50        changed |=
51            self.cell_size.update(id, v).context("qr_code update cell_size")?.is_some();
52        if let Some(_) = self.data.update(id, v).context("qr_code update data")? {
53            self.qr_data = self.data.t.as_deref().and_then(|s| {
54                match widget::qr_code::Data::new(s) {
55                    Ok(d) => Some(d),
56                    Err(e) => {
57                        error!("qr_code: failed to encode data: {e}");
58                        None
59                    }
60                }
61            });
62            changed = true;
63        }
64        Ok(changed)
65    }
66
67    fn view(&self) -> IcedElement<'_> {
68        match &self.qr_data {
69            Some(data) => {
70                let mut qr = widget::QRCode::new(data);
71                if let Some(Some(sz)) = self.cell_size.t {
72                    qr = qr.cell_size(sz as f32);
73                }
74                qr.into()
75            }
76            None => iced_widget::Space::new().into(),
77        }
78    }
79}