1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use super::{TableDataModel, TableModelEntry};
use crate::prelude::ExpansionState;
use std::cell::RefCell;
use std::collections::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
use std::rc::Rc;
use yew::virtual_dom::Key;

/// A [`super::TableModel`] based on a [`TableDataModel`] plus additional state.
pub struct StateModel<C, M>
where
    C: Clone + Eq + 'static,
    M: TableDataModel<C>,
{
    _marker: PhantomData<C>,
    model: M,
    state: Rc<RefCell<HashMap<M::Key, ExpansionState<C>>>>,
}

impl<C, M> StateModel<C, M>
where
    C: Clone + Eq + 'static,
    M: TableDataModel<C>,
{
    pub fn new(model: M, state: Rc<RefCell<HashMap<M::Key, ExpansionState<C>>>>) -> Self {
        Self {
            model,
            state,
            _marker: Default::default(),
        }
    }
}

impl<C, M> PartialEq for StateModel<C, M>
where
    C: Clone + Eq + 'static,
    M: PartialEq + TableDataModel<C>,
    M::Key: Hash,
{
    fn eq(&self, other: &Self) -> bool {
        self.state == other.state && self.model == other.model
    }
}

impl<C, M> super::TableModel<C> for StateModel<C, M>
where
    C: Clone + Eq + 'static,
    M: TableDataModel<C> + 'static,
    M::Key: Hash,
{
    type Iterator<'i> = StateModelIter<'i, Self::Key, Self::Item, C>;
    type Item = M::Item;
    type Key = M::Key;

    fn len(&self) -> usize {
        self.model.len()
    }

    fn is_empty(&self) -> bool {
        self.model.is_empty()
    }

    fn iter(&self) -> Self::Iterator<'_> {
        let state = self.state.borrow().clone();
        StateModelIter::new(self.model.iter().map(move |(key, value)| {
            let expansion = state.get(&key).cloned();
            TableModelEntry {
                key,
                value,
                expansion,
            }
        }))
    }
}

pub struct StateModelIter<'i, K, V, C>(Box<dyn Iterator<Item = TableModelEntry<'i, V, K, C>> + 'i>)
where
    K: Into<Key>,
    C: Clone + Eq;

impl<'i, K, V, C> StateModelIter<'i, K, V, C>
where
    K: Into<Key>,
    C: Clone + Eq,
{
    pub fn new<I>(iter: I) -> Self
    where
        I: Iterator<Item = TableModelEntry<'i, V, K, C>> + 'i,
    {
        Self(Box::new(iter))
    }
}

impl<'i, K, V, C> Iterator for StateModelIter<'i, K, V, C>
where
    K: Into<Key>,
    C: Clone + Eq,
{
    type Item = TableModelEntry<'i, V, K, C>;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}