1mod debug;
5mod dummy;
6mod root;
7
8use std::any::{type_name, TypeId};
9use std::cell::{Ref, RefCell, RefMut};
10use std::collections::VecDeque;
11use std::mem::replace;
12use std::rc::Rc;
13
14use anymap::AnyMap;
15use thunderdome::Arena;
16
17use crate::id::WidgetId;
18use crate::input::InputState;
19use crate::response::Response;
20use crate::widget::{ErasedWidget, Widget};
21
22use self::dummy::DummyWidget;
23use self::root::RootWidget;
24
25pub struct Dom {
27 inner: Rc<DomInner>,
28}
29
30struct DomInner {
31 nodes: RefCell<Arena<DomNode>>,
32 stack: RefCell<Vec<WidgetId>>,
33 removed_nodes: RefCell<Vec<WidgetId>>,
34 root: WidgetId,
35 globals: RefCell<AnyMap>,
36 pending_focus_request: RefCell<Option<WidgetId>>,
37}
38
39pub struct DomNode {
41 pub widget: Box<dyn ErasedWidget>,
44
45 pub parent: Option<WidgetId>,
47
48 pub children: Vec<WidgetId>,
50
51 next_child: usize,
54}
55
56impl Dom {
57 pub fn new() -> Self {
59 Self {
60 inner: Rc::new(DomInner::new()),
61 }
62 }
63
64 pub(crate) fn clone(&self) -> Self {
65 Self {
66 inner: self.inner.clone(),
67 }
68 }
69
70 pub fn start(&self) {
72 log::debug!("Dom::start()");
73
74 let mut nodes = self.inner.nodes.borrow_mut();
75 let root = nodes.get_mut(self.inner.root.index()).unwrap();
76 root.next_child = 0;
77 }
78
79 pub fn finish(&self, input: &InputState) {
81 log::debug!("Dom::finish()");
82
83 let mut nodes = self.inner.nodes.borrow_mut();
84 let mut removed_nodes = self.inner.removed_nodes.borrow_mut();
85 let root = self.inner.root;
86 trim_children(&mut nodes, &mut removed_nodes, root);
87
88 if let Some(widget_id) = self.inner.pending_focus_request.borrow_mut().take() {
89 input.set_selection(Some(widget_id));
90 }
91 }
92
93 pub fn len(&self) -> usize {
95 self.inner.nodes.borrow().len()
96 }
97
98 pub fn is_empty(&self) -> bool {
100 self.inner.nodes.borrow().is_empty()
101 }
102
103 pub fn root(&self) -> WidgetId {
105 self.inner.root
106 }
107
108 pub fn request_focus(&self, id: WidgetId) {
110 *self.inner.pending_focus_request.borrow_mut() = Some(id);
111 }
112
113 pub(crate) fn removed_nodes(&self) -> Ref<'_, [WidgetId]> {
116 let vec = self.inner.removed_nodes.borrow();
117 Ref::map(vec, AsRef::as_ref)
118 }
119
120 pub(crate) fn enter(&self, id: WidgetId) {
123 self.inner.stack.borrow_mut().push(id);
124 }
125
126 pub(crate) fn exit(&self, id: WidgetId) {
129 assert_eq!(self.inner.stack.borrow_mut().pop(), Some(id));
130 }
131
132 pub fn current(&self) -> WidgetId {
137 let stack = self.inner.stack.borrow();
138 stack.last().copied().unwrap_or(self.inner.root)
139 }
140
141 pub fn get_current(&self) -> Ref<'_, DomNode> {
143 let nodes = self.inner.nodes.borrow();
144 let index = self.current().index();
145
146 Ref::map(nodes, |nodes| nodes.get(index).unwrap())
147 }
148
149 pub fn get(&self, id: WidgetId) -> Option<Ref<'_, DomNode>> {
151 let nodes = self.inner.nodes.borrow();
152 let index = id.index();
153
154 if nodes.contains(index) {
155 Some(Ref::map(nodes, |nodes| nodes.get(index).unwrap()))
156 } else {
157 None
158 }
159 }
160
161 pub fn get_mut(&self, id: WidgetId) -> Option<RefMut<'_, DomNode>> {
163 let nodes = self.inner.nodes.borrow_mut();
164 let index = id.index();
165
166 if nodes.contains(index) {
167 Some(RefMut::map(nodes, |nodes| nodes.get_mut(index).unwrap()))
168 } else {
169 None
170 }
171 }
172
173 pub fn get_global_or_init<T, F>(&self, init: F) -> T
179 where
180 T: 'static + Clone,
181 F: FnOnce() -> T,
182 {
183 let mut globals = self.inner.globals.borrow_mut();
184 globals.entry::<T>().or_insert_with(init).clone()
185 }
186
187 pub fn do_widget<T: Widget>(&self, props: T::Props<'_>) -> Response<T::Response> {
190 let response = self.begin_widget::<T>(props);
191 self.end_widget::<T>(response.id);
192 response
193 }
194
195 pub fn begin_widget<T: Widget>(&self, props: T::Props<'_>) -> Response<T::Response> {
199 log::trace!("begin_widget::<{}>({props:#?}", type_name::<T>());
200
201 let (id, mut widget) = {
202 let mut nodes = self.inner.nodes.borrow_mut();
203 let id = next_widget(&mut nodes, self.current());
204 self.inner.stack.borrow_mut().push(id);
205
206 let node = nodes.get_mut(id.index()).unwrap();
210 let widget = replace(&mut node.widget, Box::new(DummyWidget));
211
212 node.next_child = 0;
213 (id, widget)
214 };
215
216 let response = {
218 if widget.as_ref().type_id() != TypeId::of::<T>() {
219 widget = Box::new(T::new());
220 }
221
222 let widget = widget.downcast_mut::<T>().unwrap();
223 widget.update(props)
224 };
225
226 {
228 let mut nodes = self.inner.nodes.borrow_mut();
229 let node = nodes.get_mut(id.index()).unwrap();
230 node.widget = widget;
231 }
232
233 Response::new(id, response)
234 }
235
236 pub fn end_widget<T: Widget>(&self, id: WidgetId) {
239 log::trace!("end_widget::<{}>({id:?})", type_name::<T>());
240
241 let old_top = self.inner.stack.borrow_mut().pop().unwrap_or_else(|| {
242 panic!("Cannot end_widget without an in-progress widget.");
243 });
244
245 assert!(
246 id == old_top,
247 "Dom::end_widget did not match the input widget."
248 );
249
250 let mut nodes = self.inner.nodes.borrow_mut();
251 let mut removed_nodes = self.inner.removed_nodes.borrow_mut();
252 trim_children(&mut nodes, &mut removed_nodes, id);
253 }
254}
255
256impl DomInner {
257 fn new() -> Self {
258 let mut nodes = Arena::new();
259 let root = nodes.insert(DomNode {
260 widget: Box::new(RootWidget),
261 parent: None,
262 children: Vec::new(),
263 next_child: 0,
264 });
265
266 Self {
267 globals: RefCell::new(AnyMap::new()),
268 nodes: RefCell::new(nodes),
269 removed_nodes: RefCell::new(Vec::new()),
270 stack: RefCell::new(Vec::new()),
271 root: WidgetId::new(root),
272 pending_focus_request: RefCell::new(None),
273 }
274 }
275}
276
277fn next_widget(nodes: &mut Arena<DomNode>, parent_id: WidgetId) -> WidgetId {
278 let parent = nodes.get_mut(parent_id.index()).unwrap();
279 if parent.next_child < parent.children.len() {
280 let id = parent.children[parent.next_child];
281 parent.next_child += 1;
282 id
283 } else {
284 let index = nodes.insert(DomNode {
285 widget: Box::new(DummyWidget),
286 parent: Some(parent_id),
287 children: Vec::new(),
288 next_child: 0,
289 });
290
291 let id = WidgetId::new(index);
292
293 let parent = nodes.get_mut(parent_id.index()).unwrap();
294 parent.children.push(id);
295 parent.next_child += 1;
296 id
297 }
298}
299
300fn trim_children(nodes: &mut Arena<DomNode>, removed_nodes: &mut Vec<WidgetId>, id: WidgetId) {
303 let node = nodes.get_mut(id.index()).unwrap();
304
305 if node.next_child < node.children.len() {
306 let mut queue: VecDeque<WidgetId> = VecDeque::new();
307 let to_drop = &node.children[node.next_child..];
308 queue.extend(to_drop);
309 removed_nodes.extend_from_slice(to_drop);
310
311 node.children.truncate(node.next_child);
312
313 while let Some(child_id) = queue.pop_front() {
314 removed_nodes.push(child_id);
315 let child = nodes.remove(child_id.index()).unwrap();
316 queue.extend(child.children);
317 }
318 }
319}