makepad_render/
elements.rs

1use crate::cx::*;
2use std::collections::HashMap;
3
4// These UI Element containers are the key to automating lifecycle mgmt
5// get_draw constructs items that don't exist yet,
6// and stores a redraw id. this is used by enumerate.
7// If an item is not 'get_draw'ed in a draw pass
8// it will be skipped by enumerate/iter.
9// However its not destructed and can be get-draw'ed
10// in another drawpass.
11// if you want to destruct items that werent get_draw'ed
12// call sweep on the elements collection.
13// If however you can also have 0 items in the collection,
14// You HAVE to use mark for sweep to work, since get auto-marks the collection
15// Redraw is incremental so there isn't a global 'redraw id' thats
16// always the same.
17// The idea is to use get_draw in a draw function
18// and use the iter/enumerate/get functions in the event handle code
19// This does not work for single item Element though
20// Keep a redraw ID with each element
21// to make iterating only 'redrawn in last pass' items possible
22#[derive(Clone, Default)]
23pub struct ElementsRedraw<T> {
24    redraw_id: u64,
25    item: T
26}
27
28// Multiple elements
29#[derive(Clone, Default)]
30pub struct Elements<ID, T, TEMPL>
31where ID: std::cmp::Ord + std::hash::Hash {
32    pub template: TEMPL,
33    pub element_list: Vec<ID>,
34    pub element_map: HashMap<ID, ElementsRedraw<T>>,
35    pub redraw_id: u64
36}
37
38pub struct ElementsIterator<'a, ID, T, TEMPL>
39where ID: std::cmp::Ord + std::hash::Hash {
40    elements: &'a mut Elements<ID, T, TEMPL>,
41    counter: usize
42}
43
44impl<'a, T, ID, TEMPL> ElementsIterator<'a, ID, T, TEMPL>
45where ID: std::cmp::Ord + std::hash::Hash {
46    fn new(elements: &'a mut Elements<ID, T, TEMPL>) -> Self {
47        ElementsIterator {
48            elements: elements,
49            counter: 0
50        }
51    }
52}
53
54impl<'a, ID, T, TEMPL> Iterator for ElementsIterator<'a, ID, T, TEMPL>
55where ID: std::cmp::Ord + std::hash::Hash + Clone
56{
57    type Item = &'a mut T;
58    
59    fn next(&mut self) -> Option<Self::Item> {
60        loop {
61            if self.counter >= self.elements.element_list.len() {
62                return None
63            }
64            let element_id = &self.elements.element_list[self.counter];
65            let element = self.elements.element_map.get_mut(&element_id).unwrap();
66            self.counter += 1;
67            if element.redraw_id == self.elements.redraw_id {
68                return Some(unsafe {std::mem::transmute(&mut element.item)});
69            }
70        }
71    }
72}
73
74
75pub struct ElementsIteratorNamed<'a, ID, T, TEMPL>
76where ID: std::cmp::Ord + std::hash::Hash {
77    elements: &'a mut Elements<ID, T, TEMPL>,
78    counter: usize
79}
80
81impl<'a, ID, T, TEMPL> ElementsIteratorNamed<'a, ID, T, TEMPL>
82where ID: std::cmp::Ord + std::hash::Hash {
83    fn new(elements: &'a mut Elements<ID, T, TEMPL>) -> Self {
84        ElementsIteratorNamed {
85            elements: elements,
86            counter: 0
87        }
88    }
89}
90
91impl<'a, ID, T, TEMPL> Iterator for ElementsIteratorNamed<'a, ID, T, TEMPL>
92where ID: std::cmp::Ord + std::hash::Hash + Clone
93{
94    type Item = (&'a ID, &'a mut T);
95    
96    fn next(&mut self) -> Option<Self::Item> {
97        loop {
98            if self.counter >= self.elements.element_list.len() {
99                return None
100            }
101            let element_id = &mut self.elements.element_list[self.counter];
102            let element = self.elements.element_map.get_mut(&element_id).unwrap();
103            self.counter += 1;
104            if element.redraw_id == self.elements.redraw_id {
105                return Some((unsafe {std::mem::transmute(element_id)}, unsafe {std::mem::transmute(&mut element.item)}));
106            }
107        }
108    }
109}
110
111impl<ID, T, TEMPL> Elements<ID, T, TEMPL>
112where ID: std::cmp::Ord + std::hash::Hash + Clone
113{
114    pub fn new(template: TEMPL) -> Elements<ID, T, TEMPL> {
115        Elements::<ID, T, TEMPL> {
116            template: template,
117            redraw_id: 0,
118            element_list: Vec::new(),
119            element_map: HashMap::new(),
120        }
121    }
122    
123    // if you don't atleast get_draw 1 item
124    // you have to call mark for sweep to work
125    pub fn mark(&mut self, cx: &Cx) {
126        if !cx.is_in_redraw_cycle {
127            panic!("Cannot call mark outside of redraw cycle!")
128        }
129        self.redraw_id = cx.redraw_id;
130    }
131    
132    // destructs all the items that didn't get a mark/get_draw call this time
133    pub fn sweep<F>(&mut self, cx: &mut Cx, mut destruct_callback: F)
134    where F: FnMut(&mut Cx, &mut T) {
135        if !cx.is_in_redraw_cycle {
136            panic!("Cannot call sweep outside of redraw cycle!")
137        }
138        let mut i = 0;
139        loop {
140            if i >= self.element_list.len() {
141                break;
142            }
143            let elem_id = self.element_list[i].clone();
144            let elem = self.element_map.get(&elem_id).unwrap();
145            if elem.redraw_id != self.redraw_id {
146                self.element_list.remove(i);
147                let mut elem = self.element_map.remove(&elem_id).unwrap();
148                destruct_callback(cx, &mut elem.item);
149            }
150            else {
151                i = i + 1;
152            }
153        }
154    }
155    
156    // clear all the items
157    pub fn clear<F>(&mut self, cx: &mut Cx, mut destruct_callback: F)
158    where F: FnMut(&mut Cx, &mut T) {
159        for elem_id in &self.element_list {
160            let mut elem = self.element_map.remove(&elem_id).unwrap();
161            destruct_callback(cx, &mut elem.item);
162        }
163        self.element_list.truncate(0);
164    }
165    
166    // destruct a particular item
167    /*
168    pub fn destruct(&mut self, index:ID){
169        let elem = self.element_map.get_mut(&index);
170        if let Some(elem) = elem{
171
172            self.element_list.find()
173            self.element_list.remove()
174            return Some(&mut elem.item)
175        }
176    }*/
177    
178    // iterate the set of 'last drawn' items
179    pub fn iter<'a>(&'a mut self) -> ElementsIterator<'a, ID, T, TEMPL> {
180        return ElementsIterator::new(self)
181    }
182    
183    // enumerate the set of 'last drawn' items
184    pub fn enumerate<'a>(&'a mut self) -> ElementsIteratorNamed<'a, ID, T, TEMPL> {
185        return ElementsIteratorNamed::new(self)
186    }
187    
188    // gets a particular item. Returns None when not created (yet)
189    pub fn get<'a>(&'a mut self, index: ID) -> Option<&mut T> {
190        let elem = self.element_map.get_mut(&index);
191        if let Some(elem) = elem {
192            return Some(&mut elem.item)
193        }
194        else {
195            return None
196        }
197    }
198    
199    pub fn get_draw<F>(&mut self, cx: &mut Cx, index: ID, mut insert_callback: F) -> &mut T
200    where F: FnMut(&mut Cx, &TEMPL) -> T {
201        if !cx.is_in_redraw_cycle {
202            panic!("Cannot call get_draw outside of redraw cycle!")
203        }
204        self.mark(cx);
205        let template = &self.template;
206        let element_list = &mut self.element_list;
207        let redraw_id = self.redraw_id;
208        let redraw = self.element_map.entry(index.clone()).or_insert_with( || {
209            element_list.push(index);
210            let elem = insert_callback(cx, &template);
211            ElementsRedraw {
212                redraw_id: redraw_id,
213                item: elem
214            }
215        });
216        redraw.redraw_id = redraw_id;
217        &mut redraw.item
218    }
219}
220
221
222// Multiple elements
223#[derive(Clone, Default)]
224pub struct ElementsCounted<T>
225where T: Clone {
226    pub counter: u64,
227    pub elements: Elements<u64, T, T>
228}
229
230impl<T> ElementsCounted<T>
231where T:Clone{
232    pub fn new(template: T) -> ElementsCounted<T>
233    where T: Clone {
234        ElementsCounted::<T> {
235            counter: 0,
236            elements: Elements::new(template)
237        }
238    }
239    
240    pub fn iter<'a>(&'a mut self) -> ElementsIterator<'a, u64, T, T>
241    where T: Clone {
242        return ElementsIterator::new(&mut self.elements)
243    }
244    
245    // enumerate the set of 'last drawn' items
246    pub fn enumerate<'a>(&'a mut self) -> ElementsIteratorNamed<'a, u64, T, T>
247    where T: Clone {
248        return ElementsIteratorNamed::new(&mut self.elements)
249    }
250    
251    // gets a particular item. Returns None when not created (yet)
252    pub fn get<'a>(&'a mut self, index: u64) -> Option<&mut T>
253    where T: Clone {
254        return self.elements.get(index)
255    }
256    
257    pub fn template(&mut self)->&mut T{
258        &mut self.elements.template
259    }
260    
261    pub fn get_draw(&mut self, cx: &mut Cx) -> &mut T 
262    where T:Clone{
263        if !cx.is_in_redraw_cycle {
264            panic!("Cannot call get_draw outside of redraw cycle!")
265        }
266        if self.elements.redraw_id != cx.redraw_id {
267            self.counter = 0;
268        }
269        else {
270            self.counter += 1;
271        }
272        self.elements.get_draw(cx, self.counter, | _cx, tmpl | tmpl.clone())
273    }
274}