use anathema_state::Change;
use anathema_templates::blueprints::Blueprint;
use anathema_value_resolver::Collection;
use super::{WidgetContainer, WidgetKind};
use crate::error::{Error, Result};
use crate::layout::LayoutCtx;
use crate::widget::WidgetTreeView;
#[derive(Debug)]
pub struct For<'bp> {
pub(crate) binding: &'bp str,
pub(crate) collection: Collection<'bp>,
pub(crate) body: &'bp [Blueprint],
}
impl<'bp> For<'bp> {
pub fn binding(&self) -> &'bp str {
self.binding
}
pub(super) fn update(
&mut self,
change: &Change,
mut tree: WidgetTreeView<'_, 'bp>,
ctx: &mut LayoutCtx<'_, 'bp>,
) -> Result<()> {
match change {
Change::Inserted(index) => {
let path = [*index as u16];
let transaction = tree.insert(&path);
let widget = WidgetKind::Iteration(Iteration {
loop_index: anathema_state::Value::new(*index as i64),
binding: self.binding,
});
let widget = WidgetContainer::new(widget, self.body);
let _ = transaction.commit_at(widget).ok_or_else(Error::transaction_failed)?;
for child in &tree.layout[*index as usize + 1..] {
let iter_widget = tree.values.get_mut(child.value());
let Some((
_,
WidgetContainer {
kind: WidgetKind::Iteration(iter),
..
},
)) = iter_widget
else {
unreachable!("this can only ever be an iteration")
};
*iter.loop_index.to_mut() += 1;
}
}
Change::Removed(index) => {
for child in &tree.layout[*index as usize + 1..] {
let iter_widget = tree.values.get_mut(child.value());
let Some((
_,
WidgetContainer {
kind: WidgetKind::Iteration(iter),
..
},
)) = iter_widget
else {
unreachable!("this can only ever be an iteration")
};
*iter.loop_index.to_mut() -= 1;
}
ctx.relative_remove(&[*index as u16], tree);
}
Change::Dropped | Change::Changed => {
self.collection.reload(ctx.attribute_storage);
ctx.truncate_children(&mut tree);
}
}
Ok(())
}
}
#[derive(Debug)]
pub struct Iteration<'bp> {
pub loop_index: anathema_state::Value<i64>,
pub binding: &'bp str,
}