silkenweb_dom/
element_list.rs1use std::{
3 cell::{Ref, RefCell},
4 collections::{BTreeMap, BTreeSet},
5 mem,
6 ops::Bound::{Excluded, Unbounded},
7 rc::Rc,
8};
9
10use silkenweb_reactive::{
11 clone,
12 signal::{ReadSignal, Signal},
13};
14use web_sys as dom;
15
16use crate::{DomElement, Element, ElementBuilder};
17
18pub struct ElementList<Key, Value> {
25 visible_items: Rc<RefCell<OrderedElementList<Key>>>,
26 generate_child: Rc<dyn Fn(&Value) -> Element>,
27 items: BTreeMap<Key, StoredItem<Value>>,
28 filter: Box<dyn Fn(&Value) -> ReadSignal<bool>>,
29}
30
31impl<Key, Value> ElementList<Key, Value>
32where
33 Key: 'static + Clone + Ord + Eq,
34 Value: 'static,
35{
36 pub fn new<GenerateChild, ChildElem, ParentElem>(
42 root: ParentElem,
43 generate_child: GenerateChild,
44 initial: impl Iterator<Item = (Key, Value)>,
45 ) -> Self
46 where
47 ChildElem: Into<Element>,
48 ParentElem: Into<ElementBuilder>,
49 GenerateChild: 'static + Fn(&Value) -> ChildElem,
50 {
51 let mut new = Self {
52 visible_items: Rc::new(RefCell::new(OrderedElementList::new(root.into()))),
53 generate_child: Rc::new(move |c| generate_child(c).into()),
54 items: BTreeMap::new(),
55 filter: Box::new(|_| Signal::new(true).read()),
56 };
57
58 for (key, elem) in initial {
59 new.insert(key, elem);
60 }
61
62 new
63 }
64
65 pub fn is_empty(&self) -> bool {
67 self.items.is_empty()
68 }
69
70 pub fn len(&self) -> usize {
72 self.items.len()
73 }
74
75 pub fn insert(&mut self, key: Key, item: Value) {
78 let item = Rc::new(RefCell::new(item));
79 let updater = self.updater(&key, &item);
80
81 self.items.insert(key, StoredItem { item, updater });
82 }
83
84 pub fn pop(&mut self) {
87 if let Some((key, _)) = self.items.iter().next_back() {
88 clone!(key);
90 self.items.remove(&key);
91 self.visible_items.borrow_mut().remove(&key);
92 }
93 }
94
95 pub fn remove(&mut self, key: &Key) {
98 if self.items.remove(key).is_some() {
99 self.visible_items.borrow_mut().remove(key)
100 }
101 }
102
103 pub fn filter(&mut self, f: impl 'static + Fn(&Value) -> ReadSignal<bool>) {
105 let old_items = mem::take(&mut self.items);
106 self.filter = Box::new(f);
107
108 for (key, StoredItem { item, updater }) in old_items {
109 mem::drop(updater);
110 let updater = self.updater(&key, &item);
111 self.items.insert(key, StoredItem { item, updater });
112 }
113 }
114
115 pub fn retain(&mut self, f: impl Fn(&Value) -> bool) {
118 let mut to_remove = BTreeSet::new();
120
121 for (key, value) in &self.items {
122 if !f(&value.item.borrow()) {
123 to_remove.insert(key.clone());
124 }
125 }
126
127 for key in to_remove {
128 self.remove(&key);
129 }
130 }
131
132 pub fn values(&mut self) -> impl Iterator<Item = Ref<Value>> {
136 self.items.values_mut().map(|stored| stored.item.borrow())
137 }
138
139 pub fn clear(&mut self) {
141 self.visible_items.borrow_mut().clear();
142 self.items.clear();
143 }
144
145 fn updater(&self, key: &Key, item: &Rc<RefCell<Value>>) -> ReadSignal<()> {
146 (self.filter)(&item.borrow()).map({
147 let storage = self.visible_items.clone();
148 clone!(item, key);
149 let generate_child = self.generate_child.clone();
150
151 move |&visible| {
152 if visible {
153 storage
154 .borrow_mut()
155 .insert(key.clone(), generate_child(&item.borrow()));
156 } else {
157 storage.borrow_mut().remove(&key);
158 }
159 }
160 })
161 }
162}
163
164impl<Key, T> DomElement for ElementList<Key, T> {
165 type Target = dom::Element;
166
167 fn dom_element(&self) -> Self::Target {
168 self.visible_items.borrow().dom_element()
169 }
170}
171
172pub struct OrderedElementList<Key> {
174 root: ElementBuilder,
175 items: BTreeMap<Key, Element>,
176}
177
178impl<Key> OrderedElementList<Key>
179where
180 Key: Ord + Eq,
181{
182 pub fn new<ParentElem>(root: ParentElem) -> Self
188 where
189 ParentElem: Into<ElementBuilder>,
190 {
191 let root = root.into();
192 assert!(root.element.children.is_empty());
193
194 Self {
195 root,
196 items: BTreeMap::new(),
197 }
198 }
199
200 pub fn is_empty(&self) -> bool {
201 self.items.is_empty()
202 }
203
204 pub fn len(&self) -> usize {
205 self.items.len()
206 }
207
208 pub fn insert(&mut self, key: Key, element: Element) {
210 let dom_element = element.dom_element();
213
214 if let Some((_key, next_elem)) = self.items.range((Excluded(&key), Unbounded)).next() {
215 self.root
216 .insert_child_before(&dom_element, &next_elem.dom_element());
217 } else {
218 self.root.append_child(&dom_element);
219 }
220
221 if let Some(existing_elem) = self.items.insert(key, element) {
222 self.root.remove_child(&existing_elem.dom_element());
223 }
224 }
225
226 pub fn remove(&mut self, key: &Key) {
229 if let Some(element) = self.items.remove(key) {
230 self.root.remove_child(&element.dom_element());
231 }
232 }
233
234 pub fn clear(&mut self) {
236 for element in self.items.values() {
237 self.root.remove_child(&element.dom_element());
238 }
239
240 self.items.clear();
241 }
242}
243
244impl<Key> DomElement for OrderedElementList<Key> {
245 type Target = dom::Element;
246
247 fn dom_element(&self) -> Self::Target {
248 self.root.dom_element()
249 }
250}
251
252struct StoredItem<T> {
253 item: SharedItem<T>,
254 updater: ReadSignal<()>,
255}
256
257type SharedItem<T> = Rc<RefCell<T>>;