graphix-package-gui 0.8.0

A dataflow language for UIs and network programming, GUI package
Documentation
use super::{GuiW, IcedElement};
use anyhow::{Context, Result};
use arcstr::ArcStr;
use graphix_compiler::expr::ExprId;
use graphix_rt::{GXExt, GXHandle, TRef};
use iced_widget as widget;
use log::error;
use netidx::publisher::Value;
use tokio::try_join;

pub(crate) struct QrCodeW<X: GXExt> {
    data: TRef<X, String>,
    cell_size: TRef<X, Option<f64>>,
    qr_data: Option<widget::qr_code::Data>,
}

impl<X: GXExt> QrCodeW<X> {
    pub(crate) async fn compile(gx: GXHandle<X>, source: Value) -> Result<GuiW<X>> {
        let [(_, cell_size), (_, data)] =
            source.cast_to::<[(ArcStr, u64); 2]>().context("qr_code flds")?;
        let (cell_size, data) = try_join! {
            gx.compile_ref(cell_size),
            gx.compile_ref(data),
        }?;
        let data = TRef::new(data).context("qr_code tref data")?;
        let qr_data =
            data.t.as_deref().and_then(|s| match widget::qr_code::Data::new(s) {
                Ok(d) => Some(d),
                Err(e) => {
                    error!("qr_code: failed to encode data: {e}");
                    None
                }
            });
        Ok(Box::new(Self {
            data,
            cell_size: TRef::new(cell_size).context("qr_code tref cell_size")?,
            qr_data,
        }))
    }
}

impl<X: GXExt> super::GuiWidget<X> for QrCodeW<X> {
    fn handle_update(
        &mut self,
        _rt: &tokio::runtime::Handle,
        id: ExprId,
        v: &Value,
    ) -> Result<bool> {
        let mut changed = false;
        changed |=
            self.cell_size.update(id, v).context("qr_code update cell_size")?.is_some();
        if let Some(_) = self.data.update(id, v).context("qr_code update data")? {
            self.qr_data = self.data.t.as_deref().and_then(|s| {
                match widget::qr_code::Data::new(s) {
                    Ok(d) => Some(d),
                    Err(e) => {
                        error!("qr_code: failed to encode data: {e}");
                        None
                    }
                }
            });
            changed = true;
        }
        Ok(changed)
    }

    fn view(&self) -> IcedElement<'_> {
        match &self.qr_data {
            Some(data) => {
                let mut qr = widget::QRCode::new(data);
                if let Some(Some(sz)) = self.cell_size.t {
                    qr = qr.cell_size(sz as f32);
                }
                qr.into()
            }
            None => iced_widget::Space::new().into(),
        }
    }
}