tablo_core/column/
embedded.rs1use std::sync::Arc;
4
5use derive_where::derive_where;
6use topcoat::{context::Cx, view::*};
7
8use super::{Column, ColumnBase, ColumnWidth};
9use crate::{
10 Lens,
11 schema::{EmbeddedForm, Schema},
12 values::FormValues,
13};
14
15#[derive_where(Clone, Debug)]
28pub struct EmbeddedColumn<M, T> {
29 lens: Lens<M, T>,
30 base: ColumnBase,
31 schema: Arc<Schema>,
33}
34
35impl<M, T> EmbeddedColumn<M, T>
36where
37 M: toasty::schema::Model,
38 T: EmbeddedForm,
39{
40 pub fn new(lens: Lens<M, T>) -> Self {
42 Self {
43 base: ColumnBase::new(lens.path(), ColumnWidth::Grow),
44 schema: Arc::new(T::build_schema(lens.path().clone())),
45 lens,
46 }
47 }
48
49 base_builders!();
50
51 fn spelled(&self, row: &M) -> (&Schema, FormValues) {
53 let mut values = FormValues::new();
54 self.lens
55 .read(row)
56 .write_node(self.schema.embedded_root(), &mut values);
57 (&self.schema, values)
58 }
59}
60
61impl<M, T> Column<M> for EmbeddedColumn<M, T>
62where
63 M: toasty::schema::Model + Send + Sync + 'static,
64 T: EmbeddedForm + Send + Sync + 'static,
65{
66 base_column_methods!();
67
68 fn text(&self, cx: &Cx, row: &M) -> String {
69 let (schema, values) = self.spelled(row);
70 schema
71 .embedded_root()
72 .shown(&schema.fields, &values)
73 .into_iter()
74 .filter_map(|index| {
75 let field = &schema.fields[index];
76 let value = values.text(field.name()).unwrap_or_default();
77 let read = field.read(cx, value)?;
78 Some(format!("{}: {read}", field.label().localize(cx)))
79 })
80 .collect::<Vec<_>>()
81 .join(", ")
82 }
83
84 fn entry<'a>(&self, cx: &'a Cx, row: &M) -> BoxView<'a> {
85 let (schema, values) = self.spelled(row);
86 schema.embedded_root().display(cx, &schema.fields, &values)
87 }
88
89 fn misdeclared(&self) -> Option<crate::DeclarationErrorKind> {
90 if let Some(error) = self.base.binding.misdeclared() {
91 return Some(error);
92 }
93 self.schema.declaration_errors().into_iter().next()
94 }
95}