1use std::sync::{Arc, Weak};
2
3use crate::{
4 event::{Event, EventArgs},
5 update::UPDATES,
6 var::*,
7 widget::{WidgetHandlesCtx, WidgetId, WidgetUpdateMode, node::IntoUiNode},
8};
9
10type SlotId = usize;
11
12struct SlotData {
13 item: Mutex<UiNode>,
14 slots: Mutex<SlotsData>,
15}
16#[derive(Default)]
17struct SlotsData {
18 next_slot: SlotId,
20
21 owner: Option<(SlotId, WidgetId)>,
23 move_request: Option<(SlotId, WidgetId)>,
25
26 replacement: Option<UiNode>,
28}
29impl SlotsData {
30 fn next_slot(&mut self) -> SlotId {
31 let r = self.next_slot;
32 self.next_slot = self.next_slot.wrapping_add(1);
33 r
34 }
35}
36
37pub struct ArcNode(Arc<SlotData>);
47impl Clone for ArcNode {
48 fn clone(&self) -> Self {
49 Self(self.0.clone())
50 }
51}
52impl ArcNode {
53 pub fn new(node: impl IntoUiNode) -> Self {
55 Self::new_impl(node.into_node())
56 }
57 fn new_impl(node: UiNode) -> Self {
58 ArcNode(Arc::new(SlotData {
59 item: Mutex::new(node),
60 slots: Mutex::default(),
61 }))
62 }
63
64 pub fn new_cyclic(node: impl FnOnce(WeakNode) -> UiNode) -> Self {
68 Self(Arc::new_cyclic(|wk| {
69 let node = node(WeakNode(wk.clone()));
70 SlotData {
71 item: Mutex::new(node),
72 slots: Mutex::default(),
73 }
74 }))
75 }
76
77 pub fn downgrade(&self) -> WeakNode {
79 WeakNode(Arc::downgrade(&self.0))
80 }
81
82 pub fn set(&self, new_node: impl IntoUiNode) {
86 self.set_impl(new_node.into_node())
87 }
88 fn set_impl(&self, new_node: UiNode) {
89 let mut slots = self.0.slots.lock();
90 let slots = &mut *slots;
91 if let Some((_, id)) = &slots.owner {
92 slots.replacement = Some(new_node);
94 let _ = UPDATES.update(*id);
95 } else {
96 *self.0.item.lock() = new_node;
98 }
99 }
100
101 pub fn take_when(&self, var: impl IntoVar<bool>) -> UiNode {
105 self.take_when_impl(var.into_var())
106 }
107 fn take_when_impl(&self, var: Var<bool>) -> UiNode {
108 impls::TakeSlot {
109 slot: self.0.slots.lock().next_slot(),
110 rc: self.0.clone(),
111 take: impls::TakeWhenVar { var: var.into_var() },
112 wgt_handles: WidgetHandlesCtx::new(),
113 }
114 .into_node()
115 }
116
117 pub fn take_on<A, F>(&self, event: Event<A>, filter: F, take_on_init: bool) -> UiNode
121 where
122 A: EventArgs,
123 F: FnMut(&A) -> bool + Send + 'static,
124 {
125 impls::TakeSlot {
126 slot: self.0.slots.lock().next_slot(),
127 rc: self.0.clone(),
128 take: impls::TakeOnEvent {
129 event,
130 filter,
131 take_on_init,
132 },
133 wgt_handles: WidgetHandlesCtx::new(),
134 }
135 .into_node()
136 }
137
138 pub fn take_on_init(&self) -> UiNode {
142 self.take_when(true)
143 }
144
145 pub fn try_node<R>(&self, visitor: impl FnOnce(&mut UiNode) -> R) -> Option<R> {
151 Some(visitor(&mut *self.0.item.try_lock()?))
152 }
153
154 pub fn try_context<R>(&self, update_mode: WidgetUpdateMode, visitor: impl FnOnce() -> R) -> Option<R> {
160 Some(self.0.item.try_lock()?.as_widget()?.with_context(update_mode, visitor))
161 }
162}
163
164pub struct WeakNode(Weak<SlotData>);
166impl Clone for WeakNode {
167 fn clone(&self) -> Self {
168 Self(Weak::clone(&self.0))
169 }
170}
171impl WeakNode {
172 pub fn upgrade(&self) -> Option<ArcNode> {
174 self.0.upgrade().map(ArcNode)
175 }
176}
177
178use parking_lot::Mutex;
179
180use super::UiNode;
181
182mod impls {
183 use std::sync::Arc;
184
185 use zng_layout::unit::PxSize;
186 use zng_var::Var;
187
188 use crate::{
189 event::{Event, EventArgs},
190 render::{FrameBuilder, FrameUpdate},
191 update::{UPDATES, WidgetUpdates},
192 widget::{
193 WIDGET, WidgetHandlesCtx,
194 info::{WidgetInfoBuilder, WidgetLayout, WidgetMeasure},
195 node::{UiNode, UiNodeImpl, WidgetUiNodeImpl},
196 },
197 };
198
199 use super::{SlotData, SlotId};
200
201 pub(super) trait TakeOn: Send + 'static {
202 fn take_on_init(&mut self) -> bool {
203 false
204 }
205
206 fn take_on_update(&mut self, updates: &WidgetUpdates) -> bool {
207 let _ = updates;
208 false
209 }
210 }
211
212 pub(super) struct TakeWhenVar {
213 pub(super) var: Var<bool>,
214 }
215 impl TakeOn for TakeWhenVar {
216 fn take_on_init(&mut self) -> bool {
217 WIDGET.sub_var(&self.var);
218 self.var.get()
219 }
220
221 fn take_on_update(&mut self, _: &WidgetUpdates) -> bool {
222 self.var.get_new().unwrap_or(false)
223 }
224 }
225
226 pub(super) struct TakeOnEvent<A: EventArgs, F: FnMut(&A) -> bool + Send + 'static> {
227 pub(super) event: Event<A>,
228 pub(super) filter: F,
229 pub(super) take_on_init: bool,
230 }
231 impl<A: EventArgs, F: FnMut(&A) -> bool + Send + Send + 'static> TakeOn for TakeOnEvent<A, F> {
232 fn take_on_init(&mut self) -> bool {
233 WIDGET.sub_event(&self.event);
234 self.take_on_init
235 }
236
237 fn take_on_update(&mut self, _: &WidgetUpdates) -> bool {
238 let mut any = false;
239 self.event.each_update(true, |a| any |= (self.filter)(a));
240 any
241 }
242 }
243
244 pub(super) struct TakeSlot<T: TakeOn> {
245 pub(super) slot: SlotId,
246 pub(super) rc: Arc<SlotData>,
247 pub(super) take: T,
248
249 pub(super) wgt_handles: WidgetHandlesCtx,
250 }
251 impl<T: TakeOn> TakeSlot<T> {
252 fn on_init(&mut self) {
253 if self.take.take_on_init() {
254 self.take();
255 }
256 }
257
258 fn on_deinit(&mut self) {
259 let mut was_owner = false;
260 {
261 let mut slots = self.rc.slots.lock();
262 let slots = &mut *slots;
263 if let Some((slot, _)) = &slots.owner
264 && *slot == self.slot
265 {
266 slots.owner = None;
267 was_owner = true;
268 }
269 }
270
271 if was_owner {
272 WIDGET.with_handles(&mut self.wgt_handles, || self.rc.item.lock().deinit());
273 }
274
275 self.wgt_handles.clear();
276 }
277
278 fn on_update(&mut self, updates: &WidgetUpdates) {
279 if self.is_owner() {
280 let mut slots = self.rc.slots.lock();
281 if let Some((_, id)) = slots.move_request {
282 let replacement = slots.replacement.take();
285 slots.owner = None;
286
287 drop(slots);
288
289 let mut node = self.rc.item.lock();
290 node.deinit();
291
292 WIDGET.update_info().layout().render();
293
294 if let Some(new) = replacement {
295 *node = new;
296 }
297
298 UPDATES.update(id);
299 } else if let Some(mut new) = slots.replacement.take() {
300 drop(slots);
303
304 let mut node = self.rc.item.lock();
305 WIDGET.with_handles(&mut self.wgt_handles, || {
306 node.deinit();
307 });
308 self.wgt_handles.clear();
309
310 WIDGET.with_handles(&mut self.wgt_handles, || {
311 new.init();
312 });
313 *node = new;
314
315 WIDGET.update_info().layout().render();
316 }
317 } else if self.take.take_on_update(updates) {
318 self.take();
320 } else {
321 let mut slots = self.rc.slots.lock();
322 if let Some((slot, _)) = &slots.move_request
323 && *slot == self.slot
324 && slots.owner.is_none()
325 {
326 slots.move_request = None;
327 drop(slots);
329 self.take();
330 }
331 }
332 }
333
334 fn take(&mut self) {
335 {
336 let mut slots = self.rc.slots.lock();
337 let slots = &mut *slots;
338 if let Some((sl, id)) = &slots.owner {
339 if *sl != self.slot {
340 slots.move_request = Some((self.slot, WIDGET.id()));
342 UPDATES.update(*id);
343 }
344 } else {
345 slots.owner = Some((self.slot, WIDGET.id()));
347 }
348 }
349
350 if self.is_owner() {
351 WIDGET.with_handles(&mut self.wgt_handles, || {
352 self.rc.item.lock().init();
353 });
354 WIDGET.update_info().layout().render();
355 }
356 }
357
358 fn is_owner(&self) -> bool {
359 self.rc.slots.lock().owner.as_ref().map(|(sl, _)| *sl == self.slot).unwrap_or(false)
360 }
361
362 fn delegate_owned<R>(&self, del: impl FnOnce(&UiNode) -> R) -> Option<R> {
363 if self.is_owner() { Some(del(&self.rc.item.lock())) } else { None }
364 }
365 fn delegate_owned_mut<R>(&mut self, del: impl FnOnce(&mut UiNode) -> R) -> Option<R> {
366 if self.is_owner() {
367 Some(del(&mut self.rc.item.lock()))
368 } else {
369 None
370 }
371 }
372
373 fn delegate_owned_mut_with_handles<R>(&mut self, del: impl FnOnce(&mut UiNode) -> R) -> Option<R> {
374 if self.is_owner() {
375 WIDGET.with_handles(&mut self.wgt_handles, || Some(del(&mut self.rc.item.lock())))
376 } else {
377 None
378 }
379 }
380 }
381
382 impl<T: TakeOn> UiNodeImpl for TakeSlot<T> {
383 fn children_len(&self) -> usize {
384 self.delegate_owned(|n| n.0.children_len()).unwrap_or(0)
385 }
386
387 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
388 self.delegate_owned_mut(|n| n.0.with_child(index, visitor));
389 }
390
391 fn init(&mut self) {
392 self.on_init();
393 }
394
395 fn deinit(&mut self) {
396 self.on_deinit();
397 }
398
399 fn info(&mut self, info: &mut WidgetInfoBuilder) {
400 self.delegate_owned_mut(|n| n.0.info(info));
401 }
402
403 fn update(&mut self, updates: &WidgetUpdates) {
404 self.delegate_owned_mut_with_handles(|n| n.0.update(updates));
405 self.on_update(updates);
406 }
407 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn crate::widget::node::UiNodeListObserver) {
408 self.delegate_owned_mut(|n| n.0.update_list(updates, observer));
409 self.on_update(updates);
410 }
411
412 fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
413 self.delegate_owned_mut(|n| n.0.measure(wm)).unwrap_or_default()
414 }
415 fn measure_list(
416 &mut self,
417 wm: &mut WidgetMeasure,
418 measure: &(dyn Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync),
419 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
420 ) -> PxSize {
421 self.delegate_owned_mut(|n| n.0.measure_list(wm, measure, fold_size))
422 .unwrap_or_default()
423 }
424
425 fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
426 self.delegate_owned_mut(|n| n.0.layout(wl)).unwrap_or_default()
427 }
428 fn layout_list(
429 &mut self,
430 wl: &mut WidgetLayout,
431 layout: &(dyn Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync),
432 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
433 ) -> PxSize {
434 self.delegate_owned_mut(|n| n.0.layout_list(wl, layout, fold_size))
435 .unwrap_or_default()
436 }
437
438 fn render(&mut self, frame: &mut FrameBuilder) {
439 self.delegate_owned_mut(|n| n.0.render(frame));
440 }
441 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
442 self.delegate_owned_mut(|n| n.0.render_list(frame, render));
443 }
444
445 fn render_update(&mut self, update: &mut FrameUpdate) {
446 self.delegate_owned_mut(|n| n.0.render_update(update));
447 }
448 fn render_update_list(&mut self, update: &mut FrameUpdate, render_update: &(dyn Fn(usize, &mut UiNode, &mut FrameUpdate) + Sync)) {
449 self.delegate_owned_mut(|n| n.0.render_update_list(update, render_update));
450 }
451
452 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
453 self.delegate_owned_mut(|n| n.0.for_each_child(visitor));
454 }
455
456 fn try_for_each_child(
457 &mut self,
458 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<zng_var::BoxAnyVarValue>,
459 ) -> std::ops::ControlFlow<zng_var::BoxAnyVarValue> {
460 self.delegate_owned_mut(|n| n.0.try_for_each_child(visitor))
461 .unwrap_or(std::ops::ControlFlow::Continue(()))
462 }
463
464 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
465 self.delegate_owned_mut(|n| n.0.par_each_child(visitor));
466 }
467
468 fn par_fold_reduce(
469 &mut self,
470 identity: zng_var::BoxAnyVarValue,
471 fold: &(dyn Fn(zng_var::BoxAnyVarValue, usize, &mut UiNode) -> zng_var::BoxAnyVarValue + Sync),
472 reduce: &(dyn Fn(zng_var::BoxAnyVarValue, zng_var::BoxAnyVarValue) -> zng_var::BoxAnyVarValue + Sync),
473 ) -> zng_var::BoxAnyVarValue {
474 self.delegate_owned_mut(|n| n.0.par_fold_reduce(identity.clone(), fold, reduce))
475 .unwrap_or(identity)
476 }
477
478 fn is_list(&self) -> bool {
479 self.rc.item.lock().0.is_list()
481 }
482
483 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
484 if self.delegate_owned_mut(|w| w.as_widget().is_some()).unwrap_or(false) {
485 Some(self)
486 } else {
487 None
488 }
489 }
490 }
491 impl<T: TakeOn> WidgetUiNodeImpl for TakeSlot<T> {
492 fn with_context(&mut self, update_mode: crate::widget::WidgetUpdateMode, visitor: &mut dyn FnMut()) {
493 #[cfg(debug_assertions)]
494 let mut called = 0;
495 self.delegate_owned_mut_with_handles(|w| {
496 #[cfg(debug_assertions)]
497 {
498 called = 1;
499 }
500 if let Some(mut w) = w.as_widget() {
501 #[cfg(debug_assertions)]
502 {
503 called = 2;
504 }
505 w.with_context(update_mode, visitor)
506 }
507 });
508 #[cfg(debug_assertions)]
509 match called {
510 0 => tracing::error!("ArcNode TakeSlot node taken while as_widget is held"),
511 1 => tracing::error!("ArcNode TakeSlot node was widget when as_widget returned, but not anymore"),
512 _ => {}
513 }
514 }
515 }
516}