1use std::{
4 any::{Any, TypeId},
5 fmt,
6};
7
8mod adopt;
9pub use adopt::*;
10
11mod arc;
12pub use arc::*;
13
14mod extend;
15pub use extend::*;
16
17mod match_node;
18pub use match_node::*;
19
20mod when;
21pub use when::*;
22
23mod list;
24pub use list::*;
25use zng_app_proc_macros::{ui_node, widget};
26use zng_layout::unit::PxSize;
27use zng_var::{ContextInitHandle, ResponseVar, Var};
28
29use crate::{
30 render::{FrameBuilder, FrameUpdate},
31 update::{EventUpdate, WidgetUpdates},
32};
33
34use super::{
35 WIDGET, WidgetId, WidgetUpdateMode,
36 base::{PARALLEL_VAR, Parallel},
37 info::{WidgetInfoBuilder, WidgetLayout, WidgetMeasure},
38};
39
40#[diagnostic::on_unimplemented(
47 note = "you can use `match_node` to declare a node from a closure",
48 note = "you can use `#[ui_node]` to implement `UiNode` for `{Self}`"
49)]
50pub trait UiNode: Any + Send {
51 fn init(&mut self);
64
65 fn deinit(&mut self);
77
78 fn info(&mut self, info: &mut WidgetInfoBuilder);
93
94 fn event(&mut self, update: &EventUpdate);
105
106 fn update(&mut self, updates: &WidgetUpdates);
120
121 #[must_use]
136 fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize;
137
138 #[must_use]
158 fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize;
159
160 fn render(&mut self, frame: &mut FrameBuilder);
168
169 fn render_update(&mut self, update: &mut FrameUpdate);
179
180 fn boxed(self) -> BoxedUiNode
182 where
183 Self: Sized,
184 {
185 debug_assert_ne!(self.type_id(), TypeId::of::<BoxedUiNode>());
186 Box::new(self)
187 }
188
189 #[cfg(feature = "dyn_node")]
192 fn cfg_boxed(self) -> BoxedUiNode
193 where
194 Self: Sized,
195 {
196 self.boxed()
197 }
198
199 #[cfg(not(feature = "dyn_node"))]
202 fn cfg_boxed(self) -> Self
203 where
204 Self: Sized,
205 {
206 self
207 }
208
209 fn is_widget(&self) -> bool {
215 false
216 }
217
218 fn is_nil(&self) -> bool {
223 false
224 }
225
226 fn with_context<R, F>(&mut self, update_mode: WidgetUpdateMode, f: F) -> Option<R>
235 where
236 F: FnOnce() -> R,
237 {
238 let _ = (update_mode, f);
239 None
240 }
241
242 fn into_widget(self) -> BoxedUiNode
253 where
254 Self: Sized,
255 {
256 if self.is_widget() {
257 return self.boxed();
258 }
259
260 into_widget! {
261 child = self;
262 }
263 .boxed()
264 }
265
266 fn init_widget(mut self) -> (BoxedUiNode, ResponseVar<WidgetId>)
280 where
281 Self: Sized,
282 {
283 if let Some(id) = self.with_context(WidgetUpdateMode::Ignore, || WIDGET.id()) {
284 return (self.boxed(), crate::var::response_done_var(id));
285 }
286
287 let (responder, response) = crate::var::response_var();
288 let widget = match_widget(self.boxed(), move |c, op| {
289 if let UiNodeOp::Init = op {
290 c.init();
291 let widget_id = if let Some(id) = c.with_context(WidgetUpdateMode::Ignore, || WIDGET.id()) {
292 id
293 } else {
294 c.deinit();
295 let not_widget = std::mem::replace(c.child(), NilUiNode.boxed());
296 *c.child() = not_widget.into_widget();
297
298 c.init();
299 c.with_context(WidgetUpdateMode::Ignore, || WIDGET.id()).unwrap()
300 };
301
302 responder.respond(widget_id);
303 }
304 });
305 (widget.boxed(), response)
306 }
307
308 fn downcast_unbox<T: UiNode>(self) -> Result<T, BoxedUiNode>
310 where
311 Self: Sized,
312 {
313 let boxed = self.boxed();
314 if boxed.actual_type_id() == TypeId::of::<T>() {
315 Ok(*boxed.into_any_boxed().downcast().unwrap())
316 } else if TypeId::of::<T>() == TypeId::of::<BoxedUiNode>() {
317 Ok(*(Box::new(boxed) as Box<dyn Any>).downcast().unwrap())
318 } else {
319 Err(boxed)
320 }
321 }
322
323 fn actual_type_id(&self) -> TypeId {
327 self.type_id()
328 }
329
330 fn as_any(&self) -> &dyn Any
332 where
333 Self: Sized,
334 {
335 self
336 }
337
338 fn as_any_mut(&mut self) -> &mut dyn Any
340 where
341 Self: Sized,
342 {
343 self
344 }
345
346 fn trace<E, S>(self, mut enter_mtd: E) -> BoxedUiNode
351 where
352 Self: Sized,
353 E: FnMut(UiNodeOpMethod) -> S + Send + 'static,
354 {
355 match_node(self, move |node, op| {
356 let _span = enter_mtd(op.mtd());
357 node.op(op);
358 })
359 .boxed()
360 }
361
362 fn op(&mut self, op: UiNodeOp) {
364 match op {
365 UiNodeOp::Init => self.init(),
366 UiNodeOp::Deinit => self.deinit(),
367 UiNodeOp::Info { info } => self.info(info),
368 UiNodeOp::Event { update } => self.event(update),
369 UiNodeOp::Update { updates } => self.update(updates),
370 UiNodeOp::Measure { wm, desired_size } => *desired_size = self.measure(wm),
371 UiNodeOp::Layout { wl, final_size } => *final_size = self.layout(wl),
372 UiNodeOp::Render { frame } => self.render(frame),
373 UiNodeOp::RenderUpdate { update } => self.render_update(update),
374 }
375 }
376}
377
378#[expect(non_camel_case_types)]
380#[widget($crate::widget::node::into_widget)]
381struct into_widget(crate::widget::base::WidgetBase);
382#[zng_app_proc_macros::property(CHILD, capture, widget_impl(into_widget))]
383fn child(child: impl UiNode) {}
384impl into_widget {
385 fn widget_intrinsic(&mut self) {
386 self.widget_builder().push_build_action(|b| {
387 let child = b.capture_ui_node(crate::property_id!(Self::child)).unwrap();
388 b.set_child(child);
389 });
390 }
391}
392
393pub trait UiNodeList: UiNodeListBoxed {
407 fn with_node<R, F>(&mut self, index: usize, f: F) -> R
413 where
414 F: FnOnce(&mut BoxedUiNode) -> R;
415
416 fn for_each<F>(&mut self, f: F)
418 where
419 F: FnMut(usize, &mut BoxedUiNode);
420
421 fn par_each<F>(&mut self, f: F)
423 where
424 F: Fn(usize, &mut BoxedUiNode) + Send + Sync;
425
426 fn par_fold_reduce<T, I, F, R>(&mut self, identity: I, fold: F, reduce: R) -> T
454 where
455 T: Send + 'static,
456 I: Fn() -> T + Send + Sync,
457 F: Fn(T, usize, &mut BoxedUiNode) -> T + Send + Sync,
458 R: Fn(T, T) -> T + Send + Sync;
459
460 fn len(&self) -> usize;
462
463 fn is_empty(&self) -> bool {
465 self.len() == 0
466 }
467
468 fn boxed(self) -> BoxedUiNodeList;
470
471 fn drain_into(&mut self, vec: &mut Vec<BoxedUiNode>);
473
474 fn init_all(&mut self) {
478 if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::INIT) {
479 self.par_each(|_, c| {
480 c.init();
481 });
482 } else {
483 self.for_each(|_, c| {
484 c.init();
485 })
486 }
487 }
488
489 fn deinit_all(&mut self) {
493 if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::DEINIT) {
494 self.par_each(|_, c| {
495 c.deinit();
496 });
497 } else {
498 self.for_each(|_, c| {
499 c.deinit();
500 });
501 }
502 }
503
504 fn info_all(&mut self, info: &mut WidgetInfoBuilder) {
506 if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::INFO) {
507 let p_info = self.par_fold_reduce(
508 || info.parallel_split(),
509 |mut info, _, node| {
510 node.info(&mut info);
511 info
512 },
513 |mut a, b| {
514 a.parallel_fold(b);
515 a
516 },
517 );
518 info.parallel_fold(p_info);
519 } else {
520 self.for_each(|_, c| {
521 c.info(info);
522 });
523 }
524 }
525
526 fn update_all(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
530 let _ = observer;
531
532 if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::UPDATE) {
533 self.par_each(|_, c| {
534 c.update(updates);
535 });
536 } else {
537 self.for_each(|_, c| {
538 c.update(updates);
539 });
540 }
541 }
542
543 fn event_all(&mut self, update: &EventUpdate) {
547 if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::EVENT) {
548 self.par_each(|_, c| {
549 c.event(update);
550 });
551 } else {
552 self.for_each(|_, c| {
553 c.event(update);
554 });
555 }
556 }
557
558 #[must_use]
562 fn measure_each<F, S>(&mut self, wm: &mut WidgetMeasure, measure: F, fold_size: S) -> PxSize
563 where
564 F: Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync,
565 S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
566 Self: Sized,
567 {
568 default_measure_each(self, wm, measure, fold_size)
569 }
570
571 #[must_use]
575 fn layout_each<F, S>(&mut self, wl: &mut WidgetLayout, layout: F, fold_size: S) -> PxSize
576 where
577 F: Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync,
578 S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
579 Self: Sized,
580 {
581 default_layout_each(self, wl, layout, fold_size)
582 }
583
584 fn render_all(&mut self, frame: &mut FrameBuilder) {
591 if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::RENDER) {
592 let p_frame = self.par_fold_reduce(
593 || frame.parallel_split(),
594 |mut frame, _, node| {
595 node.render(&mut frame);
596 frame
597 },
598 |mut a, b| {
599 a.parallel_fold(b);
600 a
601 },
602 );
603 frame.parallel_fold(p_frame);
604 } else {
605 self.for_each(|_, c| {
606 c.render(frame);
607 })
608 }
609 }
610
611 fn render_update_all(&mut self, update: &mut FrameUpdate) {
618 if self.len() > 1 && PARALLEL_VAR.get().contains(Parallel::RENDER) {
619 let p_update = self.par_fold_reduce(
620 || update.parallel_split(),
621 |mut update, _, node| {
622 node.render_update(&mut update);
623 update
624 },
625 |mut a, b| {
626 a.parallel_fold(b);
627 a
628 },
629 );
630 update.parallel_fold(p_update);
631 } else {
632 self.for_each(|_, c| {
633 c.render_update(update);
634 })
635 }
636 }
637 fn downcast_unbox<L: UiNodeList>(self) -> Result<L, BoxedUiNodeList>
639 where
640 Self: Sized,
641 {
642 let boxed = self.boxed();
643 if boxed.actual_type_id() == TypeId::of::<L>() {
644 Ok(*boxed.into_any_boxed().downcast().unwrap())
645 } else if TypeId::of::<L>() == TypeId::of::<BoxedUiNodeList>() {
646 Ok(*(Box::new(boxed) as Box<dyn Any>).downcast().unwrap())
647 } else {
648 Err(boxed)
649 }
650 }
651
652 fn actual_type_id(&self) -> TypeId {
656 self.type_id()
657 }
658
659 fn as_any(&mut self) -> &mut dyn Any
661 where
662 Self: Sized,
663 {
664 self
665 }
666
667 fn op(&mut self, op: UiNodeOp)
669 where
670 Self: Sized,
671 {
672 match op {
673 UiNodeOp::Init => ui_node_list_default::init_all(self),
674 UiNodeOp::Deinit => ui_node_list_default::deinit_all(self),
675 UiNodeOp::Info { info } => ui_node_list_default::info_all(self, info),
676 UiNodeOp::Event { update } => ui_node_list_default::event_all(self, update),
677 UiNodeOp::Update { updates } => ui_node_list_default::update_all(self, updates),
678 UiNodeOp::Measure { wm, desired_size } => *desired_size = ui_node_list_default::measure_all(self, wm),
679 UiNodeOp::Layout { wl, final_size } => *final_size = ui_node_list_default::layout_all(self, wl),
680 UiNodeOp::Render { frame } => ui_node_list_default::render_all(self, frame),
681 UiNodeOp::RenderUpdate { update } => ui_node_list_default::render_update_all(self, update),
682 }
683 }
684}
685
686fn default_measure_each<F, S>(self_: &mut impl UiNodeList, wm: &mut WidgetMeasure, measure: F, fold_size: S) -> PxSize
687where
688 F: Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync,
689 S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
690{
691 #[cfg(feature = "dyn_closure")]
692 let measure: Box<dyn Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync> = Box::new(measure);
693 #[cfg(feature = "dyn_closure")]
694 let fold_size: Box<dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync> = Box::new(fold_size);
695
696 default_measure_each_impl(self_, wm, measure, fold_size)
697}
698fn default_measure_each_impl<F, S>(self_: &mut impl UiNodeList, wm: &mut WidgetMeasure, measure: F, fold_size: S) -> PxSize
699where
700 F: Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync,
701 S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
702{
703 if self_.len() > 1 && PARALLEL_VAR.get().contains(Parallel::LAYOUT) {
704 let (pwm, size) = self_.par_fold_reduce(
706 || (wm.parallel_split(), PxSize::zero()),
707 |(mut a_wm, a_size), i, n| {
708 let b_size = measure(i, n, &mut a_wm);
709 (a_wm, fold_size(a_size, b_size))
710 },
711 |(mut awm, a_size), (bwm, b_size)| {
712 (
713 {
714 awm.parallel_fold(bwm);
715 awm
716 },
717 fold_size(a_size, b_size),
718 )
719 },
720 );
721 wm.parallel_fold(pwm);
722 size
723 } else {
724 let mut size = PxSize::zero();
725 self_.for_each(|i, n| {
726 let b = measure(i, n, wm);
727 size = fold_size(size, b);
728 });
729 size
730 }
731}
732
733fn default_layout_each<F, S>(self_: &mut impl UiNodeList, wl: &mut WidgetLayout, layout: F, fold_size: S) -> PxSize
734where
735 F: Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync,
736 S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
737{
738 #[cfg(feature = "dyn_closure")]
739 let layout: Box<dyn Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync> = Box::new(layout);
740 #[cfg(feature = "dyn_closure")]
741 let fold_size: Box<dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync> = Box::new(fold_size);
742
743 default_layout_each_impl(self_, wl, layout, fold_size)
744}
745fn default_layout_each_impl<F, S>(self_: &mut impl UiNodeList, wl: &mut WidgetLayout, layout: F, fold_size: S) -> PxSize
746where
747 F: Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync,
748 S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
749{
750 if self_.len() > 1 && PARALLEL_VAR.get().contains(Parallel::LAYOUT) {
751 let (pwl, size) = self_.par_fold_reduce(
753 || (wl.parallel_split(), PxSize::zero()),
754 |(mut awl, a_size), i, n| {
755 let b_size = layout(i, n, &mut awl);
756 (awl, fold_size(a_size, b_size))
757 },
758 |(mut awl, a_size), (bwl, b_size)| {
759 (
760 {
761 awl.parallel_fold(bwl);
762 awl
763 },
764 fold_size(a_size, b_size),
765 )
766 },
767 );
768 wl.parallel_fold(pwl);
769 size
770 } else {
771 let mut size = PxSize::zero();
772 self_.for_each(|i, n| {
773 let b = layout(i, n, wl);
774 size = fold_size(size, b);
775 });
776 size
777 }
778}
779
780#[doc(hidden)]
781pub mod ui_node_list_default {
782 use super::*;
783
784 pub fn init_all(list: &mut impl UiNodeList) {
785 list.init_all();
786 }
787
788 pub fn deinit_all(list: &mut impl UiNodeList) {
789 list.deinit_all();
790 }
791
792 pub fn info_all(list: &mut impl UiNodeList, info: &mut WidgetInfoBuilder) {
793 list.info_all(info)
794 }
795
796 pub fn event_all(list: &mut impl UiNodeList, update: &EventUpdate) {
797 list.event_all(update);
798 }
799
800 pub fn update_all(list: &mut impl UiNodeList, updates: &WidgetUpdates) {
801 let mut changed = false;
802
803 list.update_all(updates, &mut changed);
804
805 if changed {
806 WIDGET.layout().render();
807 }
808 }
809
810 pub fn measure_all(list: &mut impl UiNodeList, wm: &mut WidgetMeasure) -> PxSize {
811 list.measure_each(wm, |_, n, wm| n.measure(wm), PxSize::max)
812 }
813
814 pub fn layout_all(list: &mut impl UiNodeList, wl: &mut WidgetLayout) -> PxSize {
815 list.layout_each(wl, |_, n, wl| n.layout(wl), PxSize::max)
816 }
817
818 pub fn render_all(list: &mut impl UiNodeList, frame: &mut FrameBuilder) {
819 list.render_all(frame);
820 }
821
822 pub fn render_update_all(list: &mut impl UiNodeList, update: &mut FrameUpdate) {
823 list.render_update_all(update)
824 }
825}
826
827#[doc(hidden)]
828pub trait UiNodeBoxed: Any + Send {
829 fn info_boxed(&mut self, info: &mut WidgetInfoBuilder);
830 fn init_boxed(&mut self);
831 fn deinit_boxed(&mut self);
832 fn update_boxed(&mut self, updates: &WidgetUpdates);
833 fn event_boxed(&mut self, update: &EventUpdate);
834 fn measure_boxed(&mut self, wm: &mut WidgetMeasure) -> PxSize;
835 fn layout_boxed(&mut self, wl: &mut WidgetLayout) -> PxSize;
836 fn render_boxed(&mut self, frame: &mut FrameBuilder);
837 fn render_update_boxed(&mut self, update: &mut FrameUpdate);
838
839 fn is_widget_boxed(&self) -> bool;
840 fn is_nil_boxed(&self) -> bool;
841 fn with_context_boxed(&mut self, update_mode: WidgetUpdateMode, f: &mut dyn FnMut());
842 fn into_widget_boxed(self: Box<Self>) -> BoxedUiNode;
843 fn as_any_boxed(&self) -> &dyn Any;
844 fn as_any_mut_boxed(&mut self) -> &mut dyn Any;
845
846 fn actual_type_id_boxed(&self) -> TypeId;
847 fn into_any_boxed(self: Box<Self>) -> Box<dyn Any>;
848}
849
850impl<U: UiNode> UiNodeBoxed for U {
851 fn info_boxed(&mut self, info: &mut WidgetInfoBuilder) {
852 self.info(info);
853 }
854
855 fn init_boxed(&mut self) {
856 self.init();
857 }
858
859 fn deinit_boxed(&mut self) {
860 self.deinit();
861 }
862
863 fn update_boxed(&mut self, updates: &WidgetUpdates) {
864 self.update(updates);
865 }
866
867 fn event_boxed(&mut self, update: &EventUpdate) {
868 self.event(update);
869 }
870
871 fn measure_boxed(&mut self, wm: &mut WidgetMeasure) -> PxSize {
872 self.measure(wm)
873 }
874
875 fn layout_boxed(&mut self, wl: &mut WidgetLayout) -> PxSize {
876 self.layout(wl)
877 }
878
879 fn render_boxed(&mut self, frame: &mut FrameBuilder) {
880 self.render(frame);
881 }
882
883 fn render_update_boxed(&mut self, update: &mut FrameUpdate) {
884 self.render_update(update);
885 }
886
887 fn is_widget_boxed(&self) -> bool {
888 self.is_widget()
889 }
890
891 fn is_nil_boxed(&self) -> bool {
892 self.is_nil()
893 }
894
895 fn into_widget_boxed(self: Box<Self>) -> BoxedUiNode {
896 self.into_widget()
897 }
898
899 fn actual_type_id_boxed(&self) -> TypeId {
900 self.type_id()
901 }
902
903 fn into_any_boxed(self: Box<Self>) -> Box<dyn Any> {
904 self
905 }
906
907 fn with_context_boxed(&mut self, update_mode: WidgetUpdateMode, f: &mut dyn FnMut()) {
908 self.with_context(update_mode, f);
909 }
910
911 fn as_any_boxed(&self) -> &dyn Any {
912 self.as_any()
913 }
914
915 fn as_any_mut_boxed(&mut self) -> &mut dyn Any {
916 self.as_any_mut()
917 }
918}
919
920#[doc(hidden)]
921pub trait UiNodeListBoxed: Any + Send {
922 fn with_node_boxed(&mut self, index: usize, f: &mut dyn FnMut(&mut BoxedUiNode));
923 fn for_each_boxed(&mut self, f: &mut dyn FnMut(usize, &mut BoxedUiNode));
924 fn par_each_boxed(&mut self, f: &(dyn Fn(usize, &mut BoxedUiNode) + Send + Sync));
925 fn par_fold_reduce_boxed(
926 &mut self,
927 identity: &(dyn Fn() -> Box<dyn Any + Send> + Send + Sync),
928 fold: &(dyn Fn(Box<dyn Any + Send>, usize, &mut BoxedUiNode) -> Box<dyn Any + Send> + Send + Sync),
929 reduce: &(dyn Fn(Box<dyn Any + Send>, Box<dyn Any + Send>) -> Box<dyn Any + Send> + Send + Sync),
930 ) -> Box<dyn Any + Send>;
931 fn measure_each_boxed(
932 &mut self,
933 wm: &mut WidgetMeasure,
934 measure: &(dyn Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync),
935 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync),
936 ) -> PxSize;
937 fn layout_each_boxed(
938 &mut self,
939 wl: &mut WidgetLayout,
940 layout: &(dyn Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync),
941 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync),
942 ) -> PxSize;
943 fn len_boxed(&self) -> usize;
944 fn drain_into_boxed(&mut self, vec: &mut Vec<BoxedUiNode>);
945 fn init_all_boxed(&mut self);
946 fn deinit_all_boxed(&mut self);
947 fn info_all_boxed(&mut self, info: &mut WidgetInfoBuilder);
948 fn event_all_boxed(&mut self, update: &EventUpdate);
949 fn update_all_boxed(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver);
950 fn render_all_boxed(&mut self, frame: &mut FrameBuilder);
951 fn render_update_all_boxed(&mut self, update: &mut FrameUpdate);
952 fn actual_type_id_boxed(&self) -> TypeId;
953 fn into_any_boxed(self: Box<Self>) -> Box<dyn Any>;
954 fn as_any_boxed(&mut self) -> &mut dyn Any;
955}
956impl<L: UiNodeList> UiNodeListBoxed for L {
957 fn with_node_boxed(&mut self, index: usize, f: &mut dyn FnMut(&mut BoxedUiNode)) {
958 self.with_node(index, f)
959 }
960
961 fn for_each_boxed(&mut self, f: &mut dyn FnMut(usize, &mut BoxedUiNode)) {
962 self.for_each(f);
963 }
964
965 fn par_each_boxed(&mut self, f: &(dyn Fn(usize, &mut BoxedUiNode) + Send + Sync)) {
966 self.par_each(f)
967 }
968
969 fn par_fold_reduce_boxed(
970 &mut self,
971 identity: &(dyn Fn() -> Box<dyn Any + Send> + Send + Sync),
972 fold: &(dyn Fn(Box<dyn Any + Send>, usize, &mut BoxedUiNode) -> Box<dyn Any + Send> + Send + Sync),
973 reduce: &(dyn Fn(Box<dyn Any + Send>, Box<dyn Any + Send>) -> Box<dyn Any + Send> + Send + Sync),
974 ) -> Box<dyn Any + Send> {
975 self.par_fold_reduce(identity, fold, reduce)
976 }
977
978 fn measure_each_boxed(
979 &mut self,
980 wm: &mut WidgetMeasure,
981 measure: &(dyn Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync),
982 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync),
983 ) -> PxSize {
984 self.measure_each(wm, measure, fold_size)
985 }
986
987 fn layout_each_boxed(
988 &mut self,
989 wl: &mut WidgetLayout,
990 layout: &(dyn Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync),
991 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Send + Sync),
992 ) -> PxSize {
993 self.layout_each(wl, layout, fold_size)
994 }
995
996 fn len_boxed(&self) -> usize {
997 self.len()
998 }
999
1000 fn drain_into_boxed(&mut self, vec: &mut Vec<BoxedUiNode>) {
1001 self.drain_into(vec)
1002 }
1003
1004 fn init_all_boxed(&mut self) {
1005 self.init_all();
1006 }
1007
1008 fn deinit_all_boxed(&mut self) {
1009 self.deinit_all();
1010 }
1011
1012 fn info_all_boxed(&mut self, info: &mut WidgetInfoBuilder) {
1013 self.info_all(info);
1014 }
1015
1016 fn event_all_boxed(&mut self, update: &EventUpdate) {
1017 self.event_all(update);
1018 }
1019
1020 fn update_all_boxed(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
1021 self.update_all(updates, observer);
1022 }
1023
1024 fn render_all_boxed(&mut self, frame: &mut FrameBuilder) {
1025 self.render_all(frame);
1026 }
1027
1028 fn render_update_all_boxed(&mut self, update: &mut FrameUpdate) {
1029 self.render_update_all(update);
1030 }
1031
1032 fn actual_type_id_boxed(&self) -> TypeId {
1033 self.type_id()
1034 }
1035
1036 fn into_any_boxed(self: Box<Self>) -> Box<dyn Any> {
1037 self
1038 }
1039
1040 fn as_any_boxed(&mut self) -> &mut dyn Any {
1041 self.as_any()
1042 }
1043}
1044
1045pub type BoxedUiNode = Box<dyn UiNodeBoxed>;
1047
1048pub type BoxedUiNodeList = Box<dyn UiNodeListBoxed>;
1050
1051impl UiNode for BoxedUiNode {
1052 fn info(&mut self, info: &mut WidgetInfoBuilder) {
1053 self.as_mut().info_boxed(info);
1054 }
1055
1056 fn init(&mut self) {
1057 self.as_mut().init_boxed();
1058 }
1059
1060 fn deinit(&mut self) {
1061 self.as_mut().deinit_boxed();
1062 }
1063
1064 fn update(&mut self, updates: &WidgetUpdates) {
1065 self.as_mut().update_boxed(updates);
1066 }
1067
1068 fn event(&mut self, update: &EventUpdate) {
1069 self.as_mut().event_boxed(update);
1070 }
1071
1072 fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
1073 self.as_mut().measure_boxed(wm)
1074 }
1075
1076 fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
1077 self.as_mut().layout_boxed(wl)
1078 }
1079
1080 fn render(&mut self, frame: &mut FrameBuilder) {
1081 self.as_mut().render_boxed(frame);
1082 }
1083
1084 fn render_update(&mut self, update: &mut FrameUpdate) {
1085 self.as_mut().render_update_boxed(update);
1086 }
1087
1088 fn boxed(self) -> BoxedUiNode
1089 where
1090 Self: Sized,
1091 {
1092 self
1093 }
1094
1095 fn actual_type_id(&self) -> TypeId {
1096 self.as_ref().actual_type_id_boxed()
1097 }
1098
1099 fn is_widget(&self) -> bool {
1100 self.as_ref().is_widget_boxed()
1101 }
1102
1103 fn is_nil(&self) -> bool {
1104 self.as_ref().is_nil_boxed()
1105 }
1106
1107 fn with_context<R, F>(&mut self, update_mode: WidgetUpdateMode, f: F) -> Option<R>
1108 where
1109 F: FnOnce() -> R,
1110 {
1111 let mut f = Some(f);
1112 let mut r = None;
1113 self.as_mut()
1114 .with_context_boxed(update_mode, &mut || r = Some((f.take().unwrap())()));
1115 r
1116 }
1117
1118 fn into_widget(self) -> BoxedUiNode
1119 where
1120 Self: Sized,
1121 {
1122 self.into_widget_boxed()
1123 }
1124
1125 fn as_any(&self) -> &dyn Any
1126 where
1127 Self: Sized,
1128 {
1129 self.as_ref().as_any_boxed()
1130 }
1131
1132 fn as_any_mut(&mut self) -> &mut dyn Any
1133 where
1134 Self: Sized,
1135 {
1136 self.as_mut().as_any_mut_boxed()
1137 }
1138}
1139
1140impl UiNodeList for BoxedUiNodeList {
1141 fn with_node<R, F>(&mut self, index: usize, f: F) -> R
1142 where
1143 F: FnOnce(&mut BoxedUiNode) -> R,
1144 {
1145 let mut f = Some(f);
1146 let mut r = None;
1147 self.as_mut().with_node_boxed(index, &mut |n| r = Some((f.take().unwrap())(n)));
1148 r.unwrap()
1149 }
1150
1151 fn for_each<F>(&mut self, mut f: F)
1152 where
1153 F: FnMut(usize, &mut BoxedUiNode),
1154 {
1155 self.as_mut().for_each_boxed(&mut f)
1156 }
1157
1158 fn par_each<F>(&mut self, f: F)
1159 where
1160 F: Fn(usize, &mut BoxedUiNode) + Send + Sync,
1161 {
1162 self.as_mut().par_each_boxed(&f)
1163 }
1164
1165 fn par_fold_reduce<T, I, F, R>(&mut self, identity: I, fold: F, reduce: R) -> T
1166 where
1167 T: Send + 'static,
1168 I: Fn() -> T + Send + Sync,
1169 F: Fn(T, usize, &mut BoxedUiNode) -> T + Send + Sync,
1170 R: Fn(T, T) -> T + Send + Sync,
1171 {
1172 self.as_mut()
1173 .par_fold_reduce_boxed(
1174 &move || Box::new(Some(identity())),
1175 &move |mut r, i, n| {
1176 let r_mut = r.downcast_mut::<Option<T>>().unwrap();
1177 *r_mut = Some(fold(r_mut.take().unwrap(), i, n));
1178 r
1179 },
1180 &|mut a, b| {
1181 let a_mut = a.downcast_mut::<Option<T>>().unwrap();
1182 *a_mut = Some(reduce(a_mut.take().unwrap(), b.downcast::<Option<T>>().unwrap().unwrap()));
1183 a
1184 },
1185 )
1186 .downcast::<Option<T>>()
1187 .unwrap()
1188 .unwrap()
1189 }
1190
1191 fn len(&self) -> usize {
1192 self.as_ref().len_boxed()
1193 }
1194
1195 fn boxed(self) -> BoxedUiNodeList {
1196 self
1197 }
1198
1199 fn actual_type_id(&self) -> TypeId {
1200 self.as_ref().actual_type_id_boxed()
1201 }
1202
1203 fn drain_into(&mut self, vec: &mut Vec<BoxedUiNode>) {
1204 self.as_mut().drain_into_boxed(vec)
1205 }
1206
1207 fn init_all(&mut self) {
1208 self.as_mut().init_all_boxed();
1209 }
1210
1211 fn deinit_all(&mut self) {
1212 self.as_mut().deinit_all_boxed();
1213 }
1214
1215 fn update_all(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
1216 self.as_mut().update_all_boxed(updates, observer);
1217 }
1218
1219 fn info_all(&mut self, info: &mut WidgetInfoBuilder) {
1220 self.as_mut().info_all_boxed(info);
1221 }
1222
1223 fn event_all(&mut self, update: &EventUpdate) {
1224 self.as_mut().event_all_boxed(update);
1225 }
1226
1227 fn render_all(&mut self, frame: &mut FrameBuilder) {
1228 self.as_mut().render_all_boxed(frame);
1229 }
1230
1231 fn render_update_all(&mut self, update: &mut FrameUpdate) {
1232 self.as_mut().render_update_all_boxed(update);
1233 }
1234
1235 fn measure_each<F, S>(&mut self, wm: &mut WidgetMeasure, measure: F, fold_size: S) -> PxSize
1236 where
1237 F: Fn(usize, &mut BoxedUiNode, &mut WidgetMeasure) -> PxSize + Send + Sync,
1238 S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
1239 {
1240 self.as_mut().measure_each_boxed(wm, &measure, &fold_size)
1241 }
1242
1243 fn layout_each<F, S>(&mut self, wl: &mut WidgetLayout, layout: F, fold_size: S) -> PxSize
1244 where
1245 F: Fn(usize, &mut BoxedUiNode, &mut WidgetLayout) -> PxSize + Send + Sync,
1246 S: Fn(PxSize, PxSize) -> PxSize + Send + Sync,
1247 {
1248 self.as_mut().layout_each_boxed(wl, &layout, &fold_size)
1249 }
1250
1251 fn as_any(&mut self) -> &mut dyn Any
1252 where
1253 Self: Sized,
1254 {
1255 self.as_mut().as_any_boxed()
1256 }
1257}
1258
1259impl<U: UiNode> UiNode for Option<U> {
1260 fn info(&mut self, info: &mut WidgetInfoBuilder) {
1261 if let Some(node) = self {
1262 node.info(info);
1263 }
1264 }
1265
1266 fn init(&mut self) {
1267 if let Some(node) = self {
1268 node.init();
1269 }
1270 }
1271
1272 fn deinit(&mut self) {
1273 if let Some(node) = self {
1274 node.deinit();
1275 }
1276 }
1277
1278 fn event(&mut self, update: &EventUpdate) {
1279 if let Some(node) = self {
1280 node.event(update);
1281 }
1282 }
1283
1284 fn update(&mut self, updates: &WidgetUpdates) {
1285 if let Some(node) = self {
1286 node.update(updates);
1287 }
1288 }
1289
1290 fn measure(&mut self, wm: &mut WidgetMeasure) -> PxSize {
1291 if let Some(node) = self { node.measure(wm) } else { PxSize::zero() }
1292 }
1293
1294 fn layout(&mut self, wl: &mut WidgetLayout) -> PxSize {
1295 if let Some(node) = self { node.layout(wl) } else { PxSize::zero() }
1296 }
1297
1298 fn render(&mut self, frame: &mut FrameBuilder) {
1299 if let Some(node) = self {
1300 node.render(frame);
1301 }
1302 }
1303
1304 fn render_update(&mut self, update: &mut FrameUpdate) {
1305 if let Some(node) = self {
1306 node.render_update(update);
1307 }
1308 }
1309
1310 fn boxed(self) -> BoxedUiNode
1311 where
1312 Self: Sized,
1313 {
1314 match self {
1315 Some(node) => node.boxed(),
1316 None => NilUiNode.boxed(),
1317 }
1318 }
1319
1320 fn is_widget(&self) -> bool {
1321 match self {
1322 Some(node) => node.is_widget(),
1323 None => false,
1324 }
1325 }
1326
1327 fn is_nil(&self) -> bool {
1328 self.is_none()
1329 }
1330
1331 fn with_context<R, F>(&mut self, update_mode: WidgetUpdateMode, f: F) -> Option<R>
1332 where
1333 F: FnOnce() -> R,
1334 {
1335 match self {
1336 Some(node) => node.with_context(update_mode, f),
1337 None => None,
1338 }
1339 }
1340
1341 fn into_widget(self) -> BoxedUiNode
1342 where
1343 Self: Sized,
1344 {
1345 match self {
1346 Some(node) => node.into_widget(),
1347 None => NilUiNode.into_widget(),
1348 }
1349 }
1350}
1351
1352impl UiNodeList for Option<BoxedUiNode> {
1353 fn with_node<R, F>(&mut self, index: usize, f: F) -> R
1354 where
1355 F: FnOnce(&mut BoxedUiNode) -> R,
1356 {
1357 match self {
1358 Some(node) => {
1359 assert_bounds(1, index);
1360 f(node)
1361 }
1362 None => {
1363 assert_bounds(0, index);
1364 unreachable!()
1365 }
1366 }
1367 }
1368
1369 fn for_each<F>(&mut self, mut f: F)
1370 where
1371 F: FnMut(usize, &mut BoxedUiNode),
1372 {
1373 if let Some(node) = self {
1374 f(0, node);
1375 }
1376 }
1377
1378 fn par_each<F>(&mut self, f: F)
1379 where
1380 F: Fn(usize, &mut BoxedUiNode) + Send + Sync,
1381 {
1382 if let Some(node) = self {
1383 f(0, node);
1384 }
1385 }
1386
1387 fn par_fold_reduce<T, I, F, R>(&mut self, identity: I, fold: F, _: R) -> T
1388 where
1389 T: Send,
1390 I: Fn() -> T + Send + Sync,
1391 F: Fn(T, usize, &mut BoxedUiNode) -> T + Send + Sync,
1392 R: Fn(T, T) -> T + Send + Sync,
1393 {
1394 if let Some(node) = self {
1395 fold(identity(), 0, node)
1396 } else {
1397 identity()
1398 }
1399 }
1400
1401 fn len(&self) -> usize {
1402 match self {
1403 Some(_) => 1,
1404 None => 0,
1405 }
1406 }
1407
1408 fn boxed(self) -> BoxedUiNodeList {
1409 Box::new(self)
1410 }
1411
1412 fn drain_into(&mut self, vec: &mut Vec<BoxedUiNode>) {
1413 if let Some(n) = self.take() {
1414 vec.push(n);
1415 }
1416 }
1417}
1418
1419fn assert_bounds(len: usize, i: usize) {
1420 if i >= len {
1421 panic!("index `{i}` is >= len `{len}`")
1422 }
1423}
1424
1425pub struct NilUiNode;
1427#[super::ui_node(none)]
1428impl UiNode for NilUiNode {
1429 fn measure(&mut self, _: &mut WidgetMeasure) -> PxSize {
1430 PxSize::zero()
1431 }
1432
1433 fn layout(&mut self, _: &mut WidgetLayout) -> PxSize {
1434 PxSize::zero()
1435 }
1436
1437 fn is_nil(&self) -> bool {
1438 true
1439 }
1440}
1441
1442pub struct FillUiNode;
1446#[ui_node(none)]
1447impl UiNode for FillUiNode {}
1448
1449pub fn with_new_context_init_id(child: impl UiNode) -> impl UiNode {
1453 let mut id = None;
1454
1455 match_node(child, move |child, op| {
1456 let is_deinit = matches!(op, UiNodeOp::Deinit);
1457 id.get_or_insert_with(ContextInitHandle::new).with_context(|| child.op(op));
1458
1459 if is_deinit {
1460 id = None;
1461 }
1462 })
1463}
1464
1465#[cfg(test)]
1466mod tests {
1467 use super::*;
1468
1469 #[test]
1470 pub fn downcast_unbox() {
1471 fn node() -> impl UiNode {
1472 NilUiNode
1473 }
1474
1475 assert!(node().downcast_unbox::<NilUiNode>().is_ok())
1476 }
1477
1478 #[test]
1479 pub fn downcast_unbox_boxed() {
1480 fn node() -> BoxedUiNode {
1481 NilUiNode.boxed()
1482 }
1483
1484 assert!(node().downcast_unbox::<NilUiNode>().is_ok())
1485 }
1486
1487 #[test]
1488 pub fn downcast_unbox_to_boxed() {
1489 fn node() -> impl UiNode {
1490 NilUiNode.boxed()
1491 }
1492
1493 assert!(node().downcast_unbox::<BoxedUiNode>().is_ok())
1494 }
1495
1496 #[test]
1497 pub fn downcast_unbox_widget() {
1498 fn node() -> BoxedUiNode {
1499 NilUiNode.into_widget()
1500 }
1501
1502 assert!(node().downcast_unbox::<BoxedUiNode>().is_ok())
1503 }
1504}