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::{EventUpdate, 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_event(&mut self, update: &EventUpdate) -> bool {
207 let _ = update;
208 false
209 }
210
211 fn take_on_update(&mut self, updates: &WidgetUpdates) -> bool {
212 let _ = updates;
213 false
214 }
215 }
216
217 pub(super) struct TakeWhenVar {
218 pub(super) var: Var<bool>,
219 }
220 impl TakeOn for TakeWhenVar {
221 fn take_on_init(&mut self) -> bool {
222 WIDGET.sub_var(&self.var);
223 self.var.get()
224 }
225
226 fn take_on_update(&mut self, _: &WidgetUpdates) -> bool {
227 self.var.get_new().unwrap_or(false)
228 }
229 }
230
231 pub(super) struct TakeOnEvent<A: EventArgs, F: FnMut(&A) -> bool + Send + 'static> {
232 pub(super) event: Event<A>,
233 pub(super) filter: F,
234 pub(super) take_on_init: bool,
235 }
236 impl<A: EventArgs, F: FnMut(&A) -> bool + Send + Send + 'static> TakeOn for TakeOnEvent<A, F> {
237 fn take_on_init(&mut self) -> bool {
238 WIDGET.sub_event(&self.event);
239 self.take_on_init
240 }
241
242 fn take_on_event(&mut self, update: &EventUpdate) -> bool {
243 if let Some(args) = self.event.on(update) {
244 (self.filter)(args)
245 } else {
246 false
247 }
248 }
249 }
250
251 pub(super) struct TakeSlot<T: TakeOn> {
252 pub(super) slot: SlotId,
253 pub(super) rc: Arc<SlotData>,
254 pub(super) take: T,
255
256 pub(super) wgt_handles: WidgetHandlesCtx,
257 }
258 impl<T: TakeOn> TakeSlot<T> {
259 fn on_init(&mut self) {
260 if self.take.take_on_init() {
261 self.take();
262 }
263 }
264
265 fn on_deinit(&mut self) {
266 let mut was_owner = false;
267 {
268 let mut slots = self.rc.slots.lock();
269 let slots = &mut *slots;
270 if let Some((slot, _)) = &slots.owner
271 && *slot == self.slot
272 {
273 slots.owner = None;
274 was_owner = true;
275 }
276 }
277
278 if was_owner {
279 WIDGET.with_handles(&mut self.wgt_handles, || self.rc.item.lock().deinit());
280 }
281
282 self.wgt_handles.clear();
283 }
284
285 fn on_event(&mut self, update: &EventUpdate) {
286 if !self.is_owner() && self.take.take_on_event(update) {
287 self.take();
289 }
290 }
291
292 fn on_update(&mut self, updates: &WidgetUpdates) {
293 if self.is_owner() {
294 let mut slots = self.rc.slots.lock();
295 if let Some((_, id)) = slots.move_request {
296 let replacement = slots.replacement.take();
299 slots.owner = None;
300
301 drop(slots);
302
303 let mut node = self.rc.item.lock();
304 node.deinit();
305
306 WIDGET.update_info().layout().render();
307
308 if let Some(new) = replacement {
309 *node = new;
310 }
311
312 UPDATES.update(id);
313 } else if let Some(mut new) = slots.replacement.take() {
314 drop(slots);
317
318 let mut node = self.rc.item.lock();
319 WIDGET.with_handles(&mut self.wgt_handles, || {
320 node.deinit();
321 });
322 self.wgt_handles.clear();
323
324 WIDGET.with_handles(&mut self.wgt_handles, || {
325 new.init();
326 });
327 *node = new;
328
329 WIDGET.update_info().layout().render();
330 }
331 } else if self.take.take_on_update(updates) {
332 self.take();
334 } else {
335 let mut slots = self.rc.slots.lock();
336 if let Some((slot, _)) = &slots.move_request
337 && *slot == self.slot
338 && slots.owner.is_none()
339 {
340 slots.move_request = None;
341 drop(slots);
343 self.take();
344 }
345 }
346 }
347
348 fn take(&mut self) {
349 {
350 let mut slots = self.rc.slots.lock();
351 let slots = &mut *slots;
352 if let Some((sl, id)) = &slots.owner {
353 if *sl != self.slot {
354 slots.move_request = Some((self.slot, WIDGET.id()));
356 UPDATES.update(*id);
357 }
358 } else {
359 slots.owner = Some((self.slot, WIDGET.id()));
361 }
362 }
363
364 if self.is_owner() {
365 WIDGET.with_handles(&mut self.wgt_handles, || {
366 self.rc.item.lock().init();
367 });
368 WIDGET.update_info().layout().render();
369 }
370 }
371
372 fn is_owner(&self) -> bool {
373 self.rc.slots.lock().owner.as_ref().map(|(sl, _)| *sl == self.slot).unwrap_or(false)
374 }
375
376 fn delegate_owned<R>(&self, del: impl FnOnce(&UiNode) -> R) -> Option<R> {
377 if self.is_owner() { Some(del(&self.rc.item.lock())) } else { None }
378 }
379 fn delegate_owned_mut<R>(&mut self, del: impl FnOnce(&mut UiNode) -> R) -> Option<R> {
380 if self.is_owner() {
381 Some(del(&mut self.rc.item.lock()))
382 } else {
383 None
384 }
385 }
386
387 fn delegate_owned_mut_with_handles<R>(&mut self, del: impl FnOnce(&mut UiNode) -> R) -> Option<R> {
388 if self.is_owner() {
389 WIDGET.with_handles(&mut self.wgt_handles, || Some(del(&mut self.rc.item.lock())))
390 } else {
391 None
392 }
393 }
394 }
395
396 impl<T: TakeOn> UiNodeImpl for TakeSlot<T> {
397 fn children_len(&self) -> usize {
398 self.delegate_owned(|n| n.0.children_len()).unwrap_or(0)
399 }
400
401 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
402 self.delegate_owned_mut(|n| n.0.with_child(index, visitor));
403 }
404
405 fn init(&mut self) {
406 self.on_init();
407 }
408
409 fn deinit(&mut self) {
410 self.on_deinit();
411 }
412
413 fn info(&mut self, info: &mut WidgetInfoBuilder) {
414 self.delegate_owned_mut(|n| n.0.info(info));
415 }
416
417 fn event(&mut self, update: &EventUpdate) {
418 self.delegate_owned_mut_with_handles(|n| n.0.event(update));
419 self.on_event(update);
420 }
421
422 fn update(&mut self, updates: &WidgetUpdates) {
423 self.delegate_owned_mut_with_handles(|n| n.0.update(updates));
424 self.on_update(updates);
425 }
426 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn crate::widget::node::UiNodeListObserver) {
427 self.delegate_owned_mut(|n| n.0.update_list(updates, observer));
428 self.on_update(updates);
429 }
430
431 fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
432 self.delegate_owned_mut(|n| n.0.measure(wm)).unwrap_or_default()
433 }
434 fn measure_list(
435 &mut self,
436 wm: &mut WidgetMeasure,
437 measure: &(dyn Fn(usize, &mut UiNode, &mut WidgetMeasure) -> PxSize + Sync),
438 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
439 ) -> PxSize {
440 self.delegate_owned_mut(|n| n.0.measure_list(wm, measure, fold_size))
441 .unwrap_or_default()
442 }
443
444 fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
445 self.delegate_owned_mut(|n| n.0.layout(wl)).unwrap_or_default()
446 }
447 fn layout_list(
448 &mut self,
449 wl: &mut WidgetLayout,
450 layout: &(dyn Fn(usize, &mut UiNode, &mut WidgetLayout) -> PxSize + Sync),
451 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
452 ) -> PxSize {
453 self.delegate_owned_mut(|n| n.0.layout_list(wl, layout, fold_size))
454 .unwrap_or_default()
455 }
456
457 fn render(&mut self, frame: &mut FrameBuilder) {
458 self.delegate_owned_mut(|n| n.0.render(frame));
459 }
460 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
461 self.delegate_owned_mut(|n| n.0.render_list(frame, render));
462 }
463
464 fn render_update(&mut self, update: &mut FrameUpdate) {
465 self.delegate_owned_mut(|n| n.0.render_update(update));
466 }
467 fn render_update_list(&mut self, update: &mut FrameUpdate, render_update: &(dyn Fn(usize, &mut UiNode, &mut FrameUpdate) + Sync)) {
468 self.delegate_owned_mut(|n| n.0.render_update_list(update, render_update));
469 }
470
471 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
472 self.delegate_owned_mut(|n| n.0.for_each_child(visitor));
473 }
474
475 fn try_for_each_child(
476 &mut self,
477 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<zng_var::BoxAnyVarValue>,
478 ) -> std::ops::ControlFlow<zng_var::BoxAnyVarValue> {
479 self.delegate_owned_mut(|n| n.0.try_for_each_child(visitor))
480 .unwrap_or(std::ops::ControlFlow::Continue(()))
481 }
482
483 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
484 self.delegate_owned_mut(|n| n.0.par_each_child(visitor));
485 }
486
487 fn par_fold_reduce(
488 &mut self,
489 identity: zng_var::BoxAnyVarValue,
490 fold: &(dyn Fn(zng_var::BoxAnyVarValue, usize, &mut UiNode) -> zng_var::BoxAnyVarValue + Sync),
491 reduce: &(dyn Fn(zng_var::BoxAnyVarValue, zng_var::BoxAnyVarValue) -> zng_var::BoxAnyVarValue + Sync),
492 ) -> zng_var::BoxAnyVarValue {
493 self.delegate_owned_mut(|n| n.0.par_fold_reduce(identity.clone(), fold, reduce))
494 .unwrap_or(identity)
495 }
496
497 fn is_list(&self) -> bool {
498 self.rc.item.lock().0.is_list()
500 }
501
502 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
503 if self.delegate_owned_mut(|w| w.as_widget().is_some()).unwrap_or(false) {
504 Some(self)
505 } else {
506 None
507 }
508 }
509 }
510 impl<T: TakeOn> WidgetUiNodeImpl for TakeSlot<T> {
511 fn with_context(&mut self, update_mode: crate::widget::WidgetUpdateMode, visitor: &mut dyn FnMut()) {
512 #[cfg(debug_assertions)]
513 let mut called = 0;
514 self.delegate_owned_mut_with_handles(|w| {
515 #[cfg(debug_assertions)]
516 {
517 called = 1;
518 }
519 if let Some(mut w) = w.as_widget() {
520 #[cfg(debug_assertions)]
521 {
522 called = 2;
523 }
524 w.with_context(update_mode, visitor)
525 }
526 });
527 #[cfg(debug_assertions)]
528 match called {
529 0 => tracing::error!("ArcNode TakeSlot node taken while as_widget is held"),
530 1 => tracing::error!("ArcNode TakeSlot node was widget when as_widget returned, but not anymore"),
531 _ => {}
532 }
533 }
534 }
535}