1use std::sync::{Arc, Weak};
2
3use crate::{
4 event::{Event, EventArgs},
5 update::UPDATES,
6 var::*,
7 widget::{WidgetHandlesCtx, WidgetId, WidgetUpdateMode},
8};
9
10type SlotId = usize;
11
12struct SlotData<U> {
13 item: Mutex<U>,
14 slots: Mutex<SlotsData<U>>,
15}
16struct SlotsData<U> {
17 next_slot: SlotId,
19
20 owner: Option<(SlotId, WidgetId)>,
22 move_request: Option<(SlotId, WidgetId)>,
24
25 replacement: Option<U>,
27}
28impl<U> SlotsData<U> {
29 fn next_slot(&mut self) -> SlotId {
30 let r = self.next_slot;
31 self.next_slot = self.next_slot.wrapping_add(1);
32 r
33 }
34}
35impl<U> Default for SlotsData<U> {
36 fn default() -> Self {
37 Self {
38 next_slot: Default::default(),
39 owner: Default::default(),
40 move_request: Default::default(),
41 replacement: Default::default(),
42 }
43 }
44}
45
46pub struct ArcNode<U: UiNode>(Arc<SlotData<U>>);
56impl<U: UiNode> Clone for ArcNode<U> {
57 fn clone(&self) -> Self {
58 Self(self.0.clone())
59 }
60}
61impl<U: UiNode> ArcNode<U> {
62 pub fn new(node: U) -> Self {
64 ArcNode(Arc::new(SlotData {
65 item: Mutex::new(node),
66 slots: Mutex::default(),
67 }))
68 }
69
70 pub fn new_cyclic(node: impl FnOnce(WeakNode<U>) -> U) -> Self {
74 Self(Arc::new_cyclic(|wk| {
75 let node = node(WeakNode(wk.clone()));
76 SlotData {
77 item: Mutex::new(node),
78 slots: Mutex::default(),
79 }
80 }))
81 }
82
83 pub fn downgrade(&self) -> WeakNode<U> {
85 WeakNode(Arc::downgrade(&self.0))
86 }
87
88 pub fn set(&self, new_node: U) {
92 let mut slots = self.0.slots.lock();
93 let slots = &mut *slots;
94 if let Some((_, id)) = &slots.owner {
95 slots.replacement = Some(new_node);
97 let _ = UPDATES.update(*id);
98 } else {
99 *self.0.item.lock() = new_node;
101 }
102 }
103
104 pub fn take_when<I>(&self, var: I) -> TakeSlot<U, impls::TakeWhenVar<I::Var>>
108 where
109 I: IntoVar<bool>,
110 {
111 impls::TakeSlot {
112 slot: self.0.slots.lock().next_slot(),
113 rc: self.0.clone(),
114 take: impls::TakeWhenVar { var: var.into_var() },
115 delegate_init: |n| n.init(),
116 delegate_deinit: |n| n.deinit(),
117 wgt_handles: WidgetHandlesCtx::new(),
118 }
119 }
120
121 pub fn take_on<A, F>(&self, event: Event<A>, filter: F, take_on_init: bool) -> TakeSlot<U, impls::TakeOnEvent<A, F>>
125 where
126 A: EventArgs,
127 F: FnMut(&A) -> bool + Send + 'static,
128 {
129 impls::TakeSlot {
130 slot: self.0.slots.lock().next_slot(),
131 rc: self.0.clone(),
132 take: impls::TakeOnEvent {
133 event,
134 filter,
135 take_on_init,
136 },
137 delegate_init: |n| n.init(),
138 delegate_deinit: |n| n.deinit(),
139 wgt_handles: WidgetHandlesCtx::new(),
140 }
141 }
142
143 pub fn take_on_init(&self) -> TakeSlot<U, impls::TakeWhenVar<zng_var::LocalVar<bool>>> {
147 self.take_when(true)
148 }
149
150 pub fn try_context<R>(&self, update_mode: WidgetUpdateMode, f: impl FnOnce() -> R) -> Option<R> {
152 self.0.item.try_lock()?.with_context(update_mode, f)
153 }
154}
155
156pub struct WeakNode<U: UiNode>(Weak<SlotData<U>>);
158impl<U: UiNode> Clone for WeakNode<U> {
159 fn clone(&self) -> Self {
160 Self(Weak::clone(&self.0))
161 }
162}
163impl<U: UiNode> WeakNode<U> {
164 pub fn upgrade(&self) -> Option<ArcNode<U>> {
166 self.0.upgrade().map(ArcNode)
167 }
168}
169
170pub struct ArcNodeList<L: UiNodeList>(Arc<SlotData<L>>);
180impl<L: UiNodeList> Clone for ArcNodeList<L> {
181 fn clone(&self) -> Self {
182 Self(self.0.clone())
183 }
184}
185impl<L: UiNodeList> ArcNodeList<L> {
186 pub fn new(list: L) -> Self {
188 ArcNodeList(Arc::new(SlotData {
189 item: Mutex::new(list),
190 slots: Mutex::default(),
191 }))
192 }
193
194 pub fn new_cyclic(list: impl FnOnce(WeakNodeList<L>) -> L) -> Self {
198 Self(Arc::new_cyclic(|wk| {
199 let list = list(WeakNodeList(wk.clone()));
200 SlotData {
201 item: Mutex::new(list),
202 slots: Mutex::default(),
203 }
204 }))
205 }
206
207 pub fn downgrade(&self) -> WeakNodeList<L> {
209 WeakNodeList(Arc::downgrade(&self.0))
210 }
211
212 pub fn set(&self, new_list: L) {
216 let mut slots = self.0.slots.lock();
217 let slots = &mut *slots;
218 if let Some((_, id)) = &slots.owner {
219 slots.replacement = Some(new_list);
221 UPDATES.update(*id);
222 } else {
223 *self.0.item.lock() = new_list;
225 }
226 }
227
228 pub fn take_when(&self, var: impl IntoVar<bool>) -> TakeSlot<L, impl TakeOn> {
234 impls::TakeSlot {
235 slot: self.0.slots.lock().next_slot(),
236 rc: self.0.clone(),
237 take: impls::TakeWhenVar { var: var.into_var() },
238 delegate_init: |n| n.init_all(),
239 delegate_deinit: |n| n.deinit_all(),
240 wgt_handles: WidgetHandlesCtx::new(),
241 }
242 }
243
244 pub fn take_on<A: EventArgs>(
250 &self,
251 event: Event<A>,
252 filter: impl FnMut(&A) -> bool + Send + 'static,
253 take_on_init: bool,
254 ) -> TakeSlot<L, impl TakeOn> {
255 impls::TakeSlot {
256 slot: self.0.slots.lock().next_slot(),
257 rc: self.0.clone(),
258 take: impls::TakeOnEvent {
259 event,
260 filter,
261 take_on_init,
262 },
263 delegate_init: |n| n.init_all(),
264 delegate_deinit: |n| n.deinit_all(),
265 wgt_handles: WidgetHandlesCtx::new(),
266 }
267 }
268
269 pub fn take_on_init(&self) -> TakeSlot<L, impl TakeOn> {
273 self.take_when(true)
274 }
275
276 pub fn for_each_ctx(&self, update_mode: WidgetUpdateMode, mut f: impl FnMut(usize)) {
278 self.0.item.lock().for_each(|i, n| {
279 n.with_context(update_mode, || f(i));
280 })
281 }
282}
283
284pub struct WeakNodeList<L: UiNodeList>(Weak<SlotData<L>>);
286impl<L: UiNodeList> Clone for WeakNodeList<L> {
287 fn clone(&self) -> Self {
288 Self(Weak::clone(&self.0))
289 }
290}
291impl<L: UiNodeList> WeakNodeList<L> {
292 pub fn upgrade(&self) -> Option<ArcNodeList<L>> {
294 self.0.upgrade().map(ArcNodeList)
295 }
296}
297
298pub use impls::*;
299use parking_lot::Mutex;
300
301use super::{UiNode, UiNodeList};
302
303mod impls {
304 use std::sync::Arc;
305
306 use zng_layout::unit::PxSize;
307 use zng_var::Var;
308
309 use crate::{
310 event::{Event, EventArgs},
311 render::{FrameBuilder, FrameUpdate},
312 update::{EventUpdate, UPDATES, WidgetUpdates},
313 widget::{
314 WIDGET, WidgetHandlesCtx, WidgetUpdateMode,
315 info::{WidgetInfoBuilder, WidgetLayout, WidgetMeasure},
316 node::{BoxedUiNode, BoxedUiNodeList, UiNode, UiNodeList, UiNodeListObserver},
317 },
318 };
319
320 use super::{SlotData, SlotId};
321
322 #[doc(hidden)]
323 pub trait TakeOn: Send + 'static {
324 fn take_on_init(&mut self) -> bool {
325 false
326 }
327
328 fn take_on_event(&mut self, update: &EventUpdate) -> bool {
329 let _ = update;
330 false
331 }
332
333 fn take_on_update(&mut self, updates: &WidgetUpdates) -> bool {
334 let _ = updates;
335 false
336 }
337 }
338
339 #[doc(hidden)]
340 pub struct TakeWhenVar<V: Var<bool>> {
341 pub(super) var: V,
342 }
343 impl<V: Var<bool>> TakeOn for TakeWhenVar<V> {
344 fn take_on_init(&mut self) -> bool {
345 WIDGET.sub_var(&self.var);
346 self.var.get()
347 }
348
349 fn take_on_update(&mut self, _: &WidgetUpdates) -> bool {
350 self.var.get_new().unwrap_or(false)
351 }
352 }
353
354 #[doc(hidden)]
355 pub struct TakeOnEvent<A: EventArgs, F: FnMut(&A) -> bool + Send + 'static> {
356 pub(super) event: Event<A>,
357 pub(super) filter: F,
358 pub(super) take_on_init: bool,
359 }
360 impl<A: EventArgs, F: FnMut(&A) -> bool + Send + Send + 'static> TakeOn for TakeOnEvent<A, F> {
361 fn take_on_init(&mut self) -> bool {
362 WIDGET.sub_event(&self.event);
363 self.take_on_init
364 }
365
366 fn take_on_event(&mut self, update: &EventUpdate) -> bool {
367 if let Some(args) = self.event.on(update) {
368 (self.filter)(args)
369 } else {
370 false
371 }
372 }
373 }
374
375 #[doc(hidden)]
376 pub struct TakeSlot<U, T: TakeOn> {
377 pub(super) slot: SlotId,
378 pub(super) rc: Arc<SlotData<U>>,
379 pub(super) take: T,
380
381 pub(super) delegate_init: fn(&mut U),
382 pub(super) delegate_deinit: fn(&mut U),
383 pub(super) wgt_handles: WidgetHandlesCtx,
384 }
385 impl<U, T: TakeOn> TakeSlot<U, T> {
386 fn on_init(&mut self) {
387 if self.take.take_on_init() {
388 self.take();
389 }
390 }
391
392 fn on_deinit(&mut self) {
393 let mut was_owner = false;
394 {
395 let mut slots = self.rc.slots.lock();
396 let slots = &mut *slots;
397 if let Some((slot, _)) = &slots.owner {
398 if *slot == self.slot {
399 slots.owner = None;
400 was_owner = true;
401 }
402 }
403 }
404
405 if was_owner {
406 WIDGET.with_handles(&mut self.wgt_handles, || (self.delegate_deinit)(&mut *self.rc.item.lock()));
407 }
408
409 self.wgt_handles.clear();
410 }
411
412 fn on_event(&mut self, update: &EventUpdate) {
413 if !self.is_owner() && self.take.take_on_event(update) {
414 self.take();
416 }
417 }
418
419 fn on_update(&mut self, updates: &WidgetUpdates) {
420 if self.is_owner() {
421 let mut slots = self.rc.slots.lock();
422 if let Some((_, id)) = slots.move_request {
423 let replacement = slots.replacement.take();
426 slots.owner = None;
427
428 drop(slots);
429
430 let mut node = self.rc.item.lock();
431 (self.delegate_deinit)(&mut node);
432
433 WIDGET.update_info().layout().render();
434
435 if let Some(new) = replacement {
436 *node = new;
437 }
438
439 UPDATES.update(id);
440 } else if let Some(mut new) = slots.replacement.take() {
441 drop(slots);
444
445 let mut node = self.rc.item.lock();
446 WIDGET.with_handles(&mut self.wgt_handles, || {
447 (self.delegate_deinit)(&mut node);
448 });
449 self.wgt_handles.clear();
450
451 WIDGET.with_handles(&mut self.wgt_handles, || {
452 (self.delegate_init)(&mut new);
453 });
454 *node = new;
455
456 WIDGET.update_info().layout().render();
457 }
458 } else if self.take.take_on_update(updates) {
459 self.take();
461 } else {
462 let mut slots = self.rc.slots.lock();
463 if let Some((slot, _)) = &slots.move_request {
464 if *slot == self.slot && slots.owner.is_none() {
465 slots.move_request = None;
466 drop(slots);
468 self.take();
469 }
470 }
471 }
472 }
473
474 fn take(&mut self) {
475 {
476 let mut slots = self.rc.slots.lock();
477 let slots = &mut *slots;
478 if let Some((sl, id)) = &slots.owner {
479 if *sl != self.slot {
480 slots.move_request = Some((self.slot, WIDGET.id()));
482 UPDATES.update(*id);
483 }
484 } else {
485 slots.owner = Some((self.slot, WIDGET.id()));
487 }
488 }
489
490 if self.is_owner() {
491 WIDGET.with_handles(&mut self.wgt_handles, || {
492 (self.delegate_init)(&mut *self.rc.item.lock());
493 });
494 WIDGET.update_info().layout().render();
495 }
496 }
497
498 fn is_owner(&self) -> bool {
499 self.rc.slots.lock().owner.as_ref().map(|(sl, _)| *sl == self.slot).unwrap_or(false)
500 }
501
502 fn delegate_owned<R>(&self, del: impl FnOnce(&U) -> R) -> Option<R> {
503 if self.is_owner() { Some(del(&*self.rc.item.lock())) } else { None }
504 }
505 fn delegate_owned_mut<R>(&mut self, del: impl FnOnce(&mut U) -> R) -> Option<R> {
506 if self.is_owner() {
507 Some(del(&mut *self.rc.item.lock()))
508 } else {
509 None
510 }
511 }
512
513 fn delegate_owned_mut_with_handles<R>(&mut self, del: impl FnOnce(&mut U) -> R) -> Option<R> {
514 if self.is_owner() {
515 WIDGET.with_handles(&mut self.wgt_handles, || Some(del(&mut *self.rc.item.lock())))
516 } else {
517 None
518 }
519 }
520 }
521
522 impl<U: UiNode, T: TakeOn> UiNode for TakeSlot<U, T> {
523 fn init(&mut self) {
524 self.on_init();
525 }
526
527 fn deinit(&mut self) {
528 self.on_deinit();
529 }
530
531 fn info(&mut self, info: &mut WidgetInfoBuilder) {
532 self.delegate_owned_mut(|n| n.info(info));
533 }
534
535 fn event(&mut self, update: &EventUpdate) {
536 self.delegate_owned_mut_with_handles(|n| n.event(update));
537 self.on_event(update);
538 }
539
540 fn update(&mut self, updates: &WidgetUpdates) {
541 self.delegate_owned_mut_with_handles(|n| n.update(updates));
542 self.on_update(updates);
543 }
544
545 fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
546 self.delegate_owned_mut(|n| n.measure(wm)).unwrap_or_default()
547 }
548
549 fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
550 self.delegate_owned_mut(|n| n.layout(wl)).unwrap_or_default()
551 }
552
553 fn render(&mut self, frame: &mut FrameBuilder) {
554 self.delegate_owned_mut(|n| n.render(frame));
555 }
556
557 fn render_update(&mut self, update: &mut FrameUpdate) {
558 self.delegate_owned_mut(|n| n.render_update(update));
559 }
560
561 fn is_widget(&self) -> bool {
562 self.delegate_owned(UiNode::is_widget).unwrap_or(false)
563 }
564
565 fn with_context<R, F>(&mut self, update_mode: WidgetUpdateMode, f: F) -> Option<R>
566 where
567 F: FnOnce() -> R,
568 {
569 self.delegate_owned_mut(|n| n.with_context(update_mode, f)).flatten()
570 }
571 }
572
573 impl<U: UiNodeList, T: TakeOn> UiNodeList for TakeSlot<U, T> {
574 fn with_node<R, F>(&mut self, index: usize, f: F) -> R
575 where
576 F: FnOnce(&mut BoxedUiNode) -> R,
577 {
578 self.delegate_owned_mut(move |l| l.with_node(index, f))
579 .unwrap_or_else(|| panic!("index `{index}` is >= len `0`"))
580 }
581
582 fn for_each<F>(&mut self, f: F)
583 where
584 F: FnMut(usize, &mut BoxedUiNode),
585 {
586 self.delegate_owned_mut(|l| l.for_each(f));
587 }
588
589 fn par_each<F>(&mut self, f: F)
590 where
591 F: Fn(usize, &mut BoxedUiNode) + Send + Sync,
592 {
593 self.delegate_owned_mut(|l| l.par_each(f));
594 }
595
596 fn par_fold_reduce<TF, I, F, R>(&mut self, identity: I, fold: F, reduce: R) -> TF
597 where
598 TF: Send + 'static,
599 I: Fn() -> TF + Send + Sync,
600 F: Fn(TF, usize, &mut BoxedUiNode) -> TF + Send + Sync,
601 R: Fn(TF, TF) -> TF + Send + Sync,
602 {
603 self.delegate_owned_mut(|l| l.par_fold_reduce(&identity, fold, reduce))
604 .unwrap_or_else(identity)
605 }
606
607 fn len(&self) -> usize {
608 self.delegate_owned(UiNodeList::len).unwrap_or(0)
609 }
610
611 fn boxed(self) -> BoxedUiNodeList {
612 Box::new(self)
613 }
614
615 fn drain_into(&mut self, vec: &mut Vec<BoxedUiNode>) {
616 self.delegate_owned_mut(|l| l.drain_into(vec));
617 }
618
619 fn init_all(&mut self) {
620 self.on_init();
621 }
623
624 fn deinit_all(&mut self) {
625 self.on_deinit();
626 }
628
629 fn info_all(&mut self, info: &mut WidgetInfoBuilder) {
630 self.delegate_owned_mut_with_handles(|l| l.info_all(info));
631 }
632
633 fn event_all(&mut self, update: &EventUpdate) {
634 self.delegate_owned_mut_with_handles(|l| l.event_all(update));
635 self.on_event(update);
636 }
637
638 fn update_all(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
639 let _ = observer;
640 self.delegate_owned_mut_with_handles(|l| l.update_all(updates, observer));
641 self.on_update(updates);
642 }
643
644 fn render_all(&mut self, frame: &mut FrameBuilder) {
645 self.delegate_owned_mut(|l| l.render_all(frame));
646 }
647
648 fn render_update_all(&mut self, update: &mut FrameUpdate) {
649 self.delegate_owned_mut(|l| l.render_update_all(update));
650 }
651 }
652}