1use std::{any::Any, sync::Arc};
6
7use crate::WidgetFn;
8use zng_app::{
9 event::{Command, CommandHandle, CommandScope, Event, EventArgs},
10 handler::{Handler, HandlerExt as _},
11 render::{FrameBuilder, FrameValueKey},
12 update::WidgetUpdates,
13 widget::{
14 VarLayout, WIDGET,
15 border::{BORDER, BORDER_ALIGN_VAR, BORDER_OVER_VAR},
16 info::{Interactivity, WIDGET_TREE_CHANGED_EVENT},
17 node::*,
18 },
19 window::WINDOW,
20};
21use zng_app_context::{ContextLocal, LocalContext};
22use zng_layout::{
23 context::LAYOUT,
24 unit::{PxConstraints2d, PxCornerRadius, PxPoint, PxRect, PxSideOffsets, PxSize, PxVector, SideOffsets},
25};
26use zng_state_map::{StateId, StateMapRef, StateValue};
27use zng_var::*;
28
29#[doc(hidden)]
30pub use pastey::paste;
31
32#[doc(hidden)]
33pub mod __macro_util {
34 pub use zng_app::{
35 event::CommandArgs,
36 handler::{Handler, hn},
37 widget::{
38 node::{IntoUiNode, UiNode},
39 property,
40 },
41 };
42 pub use zng_var::{IntoVar, context_var};
43}
44
45pub fn with_context_var<T: VarValue>(child: impl IntoUiNode, context_var: ContextVar<T>, value: impl IntoVar<T>) -> UiNode {
135 let value = value.into_var();
136 let mut actual_value = None;
137 let mut id = None;
138
139 match_node(child, move |child, op| {
140 let mut is_deinit = false;
141 match &op {
142 UiNodeOp::Init => {
143 id = Some(ContextInitHandle::new());
144 actual_value = Some(Arc::new(value.current_context().into()));
145 }
146 UiNodeOp::Deinit => {
147 is_deinit = true;
148 }
149 _ => {}
150 }
151
152 context_var.with_context(id.clone().expect("node not inited"), &mut actual_value, || child.op(op));
153
154 if is_deinit {
155 id = None;
156 actual_value = None;
157 }
158 })
159}
160
161pub fn with_context_var_init<T: VarValue>(
170 child: impl IntoUiNode,
171 var: ContextVar<T>,
172 mut init_value: impl FnMut() -> Var<T> + Send + 'static,
173) -> UiNode {
174 let mut id = None;
175 let mut value = None;
176 match_node(child, move |child, op| {
177 let mut is_deinit = false;
178 match &op {
179 UiNodeOp::Init => {
180 id = Some(ContextInitHandle::new());
181 value = Some(Arc::new(init_value().current_context().into()));
182 }
183 UiNodeOp::Deinit => {
184 is_deinit = true;
185 }
186 _ => {}
187 }
188
189 var.with_context(id.clone().expect("node not inited"), &mut value, || child.op(op));
190
191 if is_deinit {
192 id = None;
193 value = None;
194 }
195 })
196}
197
198pub struct EventNodeBuilder<A: EventArgs, F, M> {
200 event: Event<A>,
201 filter_builder: F,
202 map_args: M,
203}
204pub struct VarEventNodeBuilder<I, F, M> {
206 init_var: I,
207 filter_builder: F,
208 map_args: M,
209}
210
211impl<A: EventArgs> EventNodeBuilder<A, (), ()> {
212 pub fn new(event: Event<A>) -> EventNodeBuilder<A, (), ()> {
214 EventNodeBuilder {
215 event,
216 filter_builder: (),
217 map_args: (),
218 }
219 }
220}
221impl<I, T> VarEventNodeBuilder<I, (), ()>
222where
223 T: VarValue,
224 I: FnMut() -> Var<T> + Send + 'static,
225{
226 pub fn new(init_var: I) -> VarEventNodeBuilder<I, (), ()> {
230 VarEventNodeBuilder {
231 init_var,
232 filter_builder: (),
233 map_args: (),
234 }
235 }
236}
237
238impl<A: EventArgs, M> EventNodeBuilder<A, (), M> {
239 pub fn filter<FB, F>(self, filter_builder: FB) -> EventNodeBuilder<A, FB, M>
257 where
258 FB: FnMut() -> F + Send + 'static,
259 F: Fn(&A) -> bool + Send + Sync + 'static,
260 {
261 EventNodeBuilder {
262 event: self.event,
263 filter_builder,
264 map_args: self.map_args,
265 }
266 }
267}
268impl<T, I, M> VarEventNodeBuilder<I, (), M>
269where
270 T: VarValue,
271 I: FnMut() -> Var<T> + Send + 'static,
272{
273 pub fn filter<FB, F>(self, filter_builder: FB) -> VarEventNodeBuilder<I, FB, M>
284 where
285 FB: FnMut() -> F + Send + 'static,
286 F: Fn(&T) -> bool + Send + Sync + 'static,
287 {
288 VarEventNodeBuilder {
289 init_var: self.init_var,
290 filter_builder,
291 map_args: self.map_args,
292 }
293 }
294}
295
296impl<A: EventArgs, F> EventNodeBuilder<A, F, ()> {
297 pub fn map_args<M, MA>(self, map_args: M) -> EventNodeBuilder<A, F, M>
301 where
302 M: FnMut(&A) -> MA + Send + 'static,
303 MA: Clone + 'static,
304 {
305 EventNodeBuilder {
306 event: self.event,
307 filter_builder: self.filter_builder,
308 map_args,
309 }
310 }
311}
312impl<T, I, F> VarEventNodeBuilder<I, F, ()>
313where
314 T: VarValue,
315 I: FnMut() -> Var<T> + Send + 'static,
316{
317 pub fn map_args<M, MA>(self, map_args: M) -> VarEventNodeBuilder<I, F, M>
325 where
326 M: FnMut(&T) -> MA + Send + 'static,
327 MA: Clone + 'static,
328 {
329 VarEventNodeBuilder {
330 init_var: self.init_var,
331 filter_builder: self.filter_builder,
332 map_args,
333 }
334 }
335}
336
337impl<A, F, FB, MA, M> EventNodeBuilder<A, FB, M>
339where
340 A: EventArgs,
341 F: Fn(&A) -> bool + Send + Sync + 'static,
342 FB: FnMut() -> F + Send + 'static,
343 MA: Clone + 'static,
344 M: FnMut(&A) -> MA + Send + 'static,
345{
346 pub fn build<const PRE: bool>(self, child: impl IntoUiNode, handler: Handler<MA>) -> UiNode {
350 let Self {
351 event,
352 mut filter_builder,
353 mut map_args,
354 } = self;
355 let mut handler = handler.into_wgt_runner();
356 match_node(child, move |child, op| match op {
357 UiNodeOp::Init => {
358 WIDGET.sub_event_when(&event, filter_builder());
359 }
360 UiNodeOp::Deinit => {
361 handler.deinit();
362 }
363 UiNodeOp::Update { updates } => {
364 if !PRE {
365 child.update(updates);
366 }
367
368 handler.update();
369
370 let mut f = None;
371 event.each_update(false, |args| {
372 if f.get_or_insert_with(&mut filter_builder)(args) {
373 handler.event(&map_args(args));
374 }
375 });
376 }
377 _ => {}
378 })
379 }
380}
381
382impl<T, I, F, FB, MA, M> VarEventNodeBuilder<I, FB, M>
384where
385 T: VarValue,
386 I: FnMut() -> Var<T> + Send + 'static,
387 F: Fn(&T) -> bool + Send + Sync + 'static,
388 FB: FnMut() -> F + Send + 'static,
389 MA: Clone + 'static,
390 M: FnMut(&T) -> MA + Send + 'static,
391{
392 pub fn build<const PRE: bool>(self, child: impl IntoUiNode, handler: Handler<MA>) -> UiNode {
396 let Self {
397 mut init_var,
398 mut filter_builder,
399 mut map_args,
400 } = self;
401 let mut handler = handler.into_wgt_runner();
402 let mut var = None;
403 match_node(child, move |child, op| match op {
404 UiNodeOp::Init => {
405 let v = init_var();
406 let f = filter_builder();
407 WIDGET.sub_var_when(&v, move |a| f(a.value()));
408 var = Some(v);
409 }
410 UiNodeOp::Deinit => {
411 handler.deinit();
412 var = None;
413 }
414 UiNodeOp::Update { updates } => {
415 if PRE {
416 child.update(updates);
417 }
418
419 handler.update();
420
421 var.as_ref().unwrap().with_new(|t| {
422 if filter_builder()(t) {
423 handler.event(&map_args(t));
424 }
425 });
426 }
427 _ => {}
428 })
429 }
430}
431
432impl<A, F, FB> EventNodeBuilder<A, FB, ()>
434where
435 A: EventArgs,
436 F: Fn(&A) -> bool + Send + Sync + 'static,
437 FB: FnMut() -> F + Send + 'static,
438{
439 pub fn build<const PRE: bool>(self, child: impl IntoUiNode, handler: Handler<A>) -> UiNode {
443 let Self {
444 event, mut filter_builder, ..
445 } = self;
446 let mut handler = handler.into_wgt_runner();
447 match_node(child, move |child, op| match op {
448 UiNodeOp::Init => {
449 WIDGET.sub_event_when(&event, filter_builder());
450 }
451 UiNodeOp::Deinit => {
452 handler.deinit();
453 }
454 UiNodeOp::Update { updates } => {
455 if !PRE {
456 child.update(updates);
457 }
458
459 handler.update();
460
461 let mut f = None;
462 event.each_update(false, |args| {
463 if f.get_or_insert_with(&mut filter_builder)(args) {
464 handler.event(args);
465 }
466 });
467 }
468 _ => {}
469 })
470 }
471}
472impl<T, I, F, FB> VarEventNodeBuilder<I, FB, ()>
474where
475 T: VarValue,
476 I: FnMut() -> Var<T> + Send + 'static,
477 F: Fn(&T) -> bool + Send + Sync + 'static,
478 FB: FnMut() -> F + Send + 'static,
479{
480 pub fn build<const PRE: bool>(self, child: impl IntoUiNode, handler: Handler<T>) -> UiNode {
484 let Self {
485 mut init_var,
486 mut filter_builder,
487 ..
488 } = self;
489 let mut handler = handler.into_wgt_runner();
490 let mut var = None;
491 match_node(child, move |child, op| match op {
492 UiNodeOp::Init => {
493 let v = init_var();
494 let f = filter_builder();
495 WIDGET.sub_var_when(&v, move |a| f(a.value()));
496 var = Some(v);
497 }
498 UiNodeOp::Deinit => {
499 handler.deinit();
500 var = None;
501 }
502 UiNodeOp::Update { updates } => {
503 if !PRE {
504 child.update(updates);
505 }
506
507 handler.update();
508
509 var.as_ref().unwrap().with_new(|t| {
510 if filter_builder()(t) {
511 handler.event(t);
512 }
513 });
514 }
515 _ => {}
516 })
517 }
518}
519
520impl<A> EventNodeBuilder<A, (), ()>
522where
523 A: EventArgs,
524{
525 pub fn build<const PRE: bool>(self, child: impl IntoUiNode, handler: Handler<A>) -> UiNode {
529 let Self { event, .. } = self;
530 let mut handler = handler.into_wgt_runner();
531 match_node(child, move |child, op| match op {
532 UiNodeOp::Init => {
533 WIDGET.sub_event(&event);
534 }
535 UiNodeOp::Deinit => {
536 handler.deinit();
537 }
538 UiNodeOp::Update { updates } => {
539 if !PRE {
540 child.update(updates);
541 }
542
543 handler.update();
544
545 event.each_update(false, |args| {
546 handler.event(args);
547 });
548 }
549 _ => {}
550 })
551 }
552}
553impl<T, I> VarEventNodeBuilder<I, (), ()>
555where
556 T: VarValue,
557 I: FnMut() -> Var<T> + Send + 'static,
558{
559 pub fn build<const PRE: bool>(self, child: impl IntoUiNode, handler: Handler<T>) -> UiNode {
563 let Self { mut init_var, .. } = self;
564 let mut handler = handler.into_wgt_runner();
565 let mut var = None;
566 match_node(child, move |child, op| match op {
567 UiNodeOp::Init => {
568 let v = init_var();
569 WIDGET.sub_var(&v);
570 var = Some(v);
571 }
572 UiNodeOp::Deinit => {
573 handler.deinit();
574 var = None;
575 }
576 UiNodeOp::Update { updates } => {
577 if !PRE {
578 child.update(updates);
579 }
580
581 handler.update();
582
583 var.as_ref().unwrap().with_new(|t| {
584 handler.event(t);
585 });
586 }
587 _ => {}
588 })
589 }
590}
591
592impl<A, MA, M> EventNodeBuilder<A, (), M>
594where
595 A: EventArgs,
596 MA: Clone + 'static,
597 M: FnMut(&A) -> MA + Send + 'static,
598{
599 pub fn build<const PRE: bool>(self, child: impl IntoUiNode, handler: Handler<MA>) -> UiNode {
603 self.filter(|| |_| true).build::<PRE>(child, handler)
604 }
605}
606impl<T, I, MA, M> VarEventNodeBuilder<I, (), M>
608where
609 T: VarValue,
610 I: FnMut() -> Var<T> + Send + 'static,
611 MA: Clone + 'static,
612 M: FnMut(&T) -> MA + Send + 'static,
613{
614 pub fn build<const PRE: bool>(self, child: impl IntoUiNode, handler: Handler<MA>) -> UiNode {
618 self.filter(|| |_| true).build::<PRE>(child, handler)
619 }
620}
621
622#[macro_export]
683macro_rules! event_property {
684 ($(
685 $(#[$meta:meta])+
686 $vis:vis fn $on_ident:ident $(< $on_pre_ident:ident $(,)?>)? (
687 $child:ident: impl $IntoUiNode:path,
688 $handler:ident: $Handler:ty $(,)?
689 ) -> $UiNode:path {
690 $($body:tt)+
691 }
692 )+) => {$(
693 $crate::event_property_impl! {
694 $(#[$meta])+
695 $vis fn $on_ident $(< $on_pre_ident >)? ($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
696 $($body)+
697 }
698 }
699 )+};
700}
701#[doc(inline)]
702pub use event_property;
703
704#[doc(hidden)]
705#[macro_export]
706macro_rules! event_property_impl {
707 (
708 $(#[$meta:meta])+
709 $vis:vis fn $on_ident:ident < $on_pre_ident:ident > ($child:ident : impl $IntoUiNode:path, $handler:ident : $Handler:ty) -> $UiNode:path {
710 const $PRE:ident : bool;
711 $($body:tt)+
712 }
713 ) => {
714 $(#[$meta])+
715 #[doc = concat!("[`", stringify!($pn_pre_ident), "`](fn@", stringify!($pn_pre_ident), ")")]
720 $vis fn $on_ident($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
722 const $PRE: bool = false;
723 $($body)+
724 }
725
726 $(#[$meta])+
727 #[doc = concat!("[`", stringify!($pn_ident), "`](fn@", stringify!($pn_ident), ")")]
732 $vis fn $on_pre_ident($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
734 const $PRE: bool = true;
735 $($body)+
736 }
737 };
738
739 (
740 $(#[$meta:meta])+
741 $vis:vis fn $on_ident:ident ($child:ident : impl $IntoUiNode:path, $handler:ident : $Handler:path) -> $UiNode:path {
742 $($body:tt)+
743 }
744 ) => {
745 $(#[$meta])+
746 $vis fn $on_ident($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
751 $($body)+
752 }
753 };
754}
755
756#[macro_export]
794macro_rules! command_property {
795 ($(
796 $(#[$($attr:tt)+])+
797 $vis:vis fn $on_ident:ident $(< $on_pre_ident:ident $(, $can_ident:ident)? $(,)?>)? (
798 $child:ident: impl $IntoUiNode:path,
799 $handler:ident: $Handler:ty $(,)?
800 ) -> $UiNode:path {
801 $COMMAND:path
802 }
803 )+) => {$(
804 $crate::command_property_impl! {
805 not_property {}
806 attributes {
807 $(#[$($attr)+])+
808 }
809 fn {
810 $vis fn $on_ident$(<$on_pre_ident $(, $can_ident)?>)?($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
811 $COMMAND
812 }
813 }
814 }
815 )+};
816}
817#[doc(inline)]
818pub use command_property;
819#[doc(hidden)]
820#[macro_export]
821macro_rules! command_property_impl {
822 (
824 not_property { $($not_property:tt)* }
825 attributes {
826 #[property $property:tt]
827 $($attributes:tt)*
828 }
829 fn { $($fn:tt)+ }
830 ) => {
831 $crate::command_property_impl! {
832 property { $property }
833 attributes {
834 $($not_property)*
835 $($attributes)*
836 }
837 fn { $($fn)+ }
838 }
839 };
840 (
842 not_property { $($not_property:tt)* }
843 attributes {
844 #[$($some_attr:tt)*]
845 $($attributes:tt)*
846 }
847 fn { $($fn:tt)+ }
848 ) => {
849 $crate::command_property_impl! {
850 not_property {
851 $($not_property)*
852 #[$($some_attr)*]
853 }
854 attributes {
855 $($attributes)+
856 }
857 fn { $($fn)+ }
858 }
859 };
860 (
862 not_property { $($not_property:tt)* }
863 attributes { }
864 fn { $($fn:tt)+ }
865 ) => {
866 compile_error!{"expected #[property(...)] attribute"}
867 };
868
869 (
871 property { ( $p_group:expr $(, default $p_default:tt)? $(, widget_impl $p_widget_impl:tt)? $(,)? ) }
872 attributes { $(#[$meta:meta])* }
873 fn {
874 $vis:vis fn $on_ident:ident < $on_pre_ident:ident, $can_ident:ident> (
875 $child:ident: impl $IntoUiNode:path,
876 $handler:ident: $Handler:ty
877 ) -> $UiNode:path {
878 $COMMAND:path
879 }
880 }
881 ) => {
882 $crate::node::paste! {
883 $crate::node::__macro_util::context_var! {
884 #[doc = concat!("[`", stringify!($on_ident), "`](fn@", stringify!($on_ident), ")")]
886 #[doc = concat!("[`", stringify!($on_pre_ident), "`](fn@", stringify!($on_pre_ident), ")")]
888 #[doc = concat!("[`", stringify!($can_ident), "`](fn@", stringify!($can_ident), ")")]
892 $vis static [<$can_ident:upper _VAR>]: bool = true;
894 }
895
896 #[doc = concat!("[`", stringify!($on_ident), "`](fn@", stringify!($on_ident), ")")]
898 #[doc = concat!("[`", stringify!($on_pre_ident), "`](fn@", stringify!($on_pre_ident), ")")]
900 #[doc = "Sets the [`"$can_ident:upper "_VAR`]."]
903 #[$crate::node::__macro_util::property(CONTEXT, default([<$can_ident:upper _VAR>]) $(, widget_impl $p_widget_impl)? )]
904 $vis fn $can_ident(
905 child: impl $crate::node::__macro_util::IntoUiNode,
906 enabled: impl $crate::node::__macro_util::IntoVar<bool>,
907 ) -> $crate::node::__macro_util::UiNode {
908 $crate::node::with_context_var(child, self::[<$can_ident:upper _VAR>], enabled)
909 }
910
911 $crate::event_property! {
912 $(#[$meta])*
913 #[$crate::node::__macro_util::property ( $p_group $(, default $p_default)? $(, widget_impl $p_widget_impl)? )]
914 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
919 #[doc = concat!("[`", stringify!($can_ident), "`](fn@", stringify!($can_ident), ")")]
924 $vis fn $on_ident<$on_pre_ident>($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
926 const PRE: bool;
927 let child = $crate::node::EventNodeBuilder::new(*$COMMAND)
928 .filter(|| {
929 let enabled = self::[<$can_ident:upper _VAR>].current_context();
930 move |_| enabled.get()
931 })
932 .build::<PRE>($child, $handler);
933 $crate::node::command_contextual_enabled(child, $COMMAND, [<$can_ident:upper _VAR>])
934 }
935 }
936 }
937 };
938 (
940 property { $property:tt }
941 attributes { $(#[$meta:meta])* }
942 fn {
943 $vis:vis fn $on_ident:ident< $on_pre_ident:ident> (
944 $child:ident: impl $IntoUiNode:path,
945 $handler:ident: $Handler:ty
946 ) -> $UiNode:path {
947 $COMMAND:path
948 }
949 }
950 ) => {
951 $crate::event_property! {
952 #[$crate::node::__macro_util::property $property]
953 $(#[$meta])*
954 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
959 $vis fn $on_ident<$on_pre_ident>($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
964 const PRE: bool;
965 let child = $crate::node::EventNodeBuilder::new(*$COMMAND).build::<PRE>($child, $handler);
966 $crate::node::command_always_enabled(child, $COMMAND)
967 }
968 }
969 };
970 (
971 property { $property:tt }
972 attributes { $(#[$meta:meta])* }
973 fn {
974 $vis:vis fn $on_ident:ident (
975 $child:ident: impl $IntoUiNode:path,
976 $handler:ident: $Handler:ty
977 ) -> $UiNode:path {
978 $COMMAND:path
979 }
980 }
981 ) => {
982 $crate::event_property! {
983 #[$crate::node::__macro_util::property $property]
984 $(#[$meta])*
985 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
990 $vis fn $on_ident($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
995 let child = $crate::node::EventNodeBuilder::new(*$COMMAND).build::<false>($child, $handler);
996 $crate::node::command_always_enabled(child, $COMMAND)
997 }
998 }
999 };
1000}
1001
1002fn validate_cmd(cmd: Command) {
1003 if !matches!(cmd.scope(), CommandScope::App) {
1004 tracing::error!("command for command property cannot be scoped, {cmd:?} scope will be ignored");
1005 }
1006}
1007
1008#[doc(hidden)]
1009pub fn command_always_enabled(child: UiNode, cmd: Command) -> UiNode {
1010 let mut _wgt_handle = CommandHandle::dummy();
1011 let mut _win_handle = CommandHandle::dummy();
1012 match_node(child, move |_, op| match op {
1013 UiNodeOp::Init => {
1014 validate_cmd(cmd);
1015 _wgt_handle = cmd.scoped(WIDGET.id()).subscribe(true);
1016 if WIDGET.parent_id().is_none() {
1017 _win_handle = cmd.scoped(WINDOW.id()).subscribe(true);
1018 }
1019 }
1020 UiNodeOp::Deinit => {
1021 _wgt_handle = CommandHandle::dummy();
1022 _win_handle = CommandHandle::dummy();
1023 }
1024 _ => {}
1025 })
1026}
1027
1028#[doc(hidden)]
1029pub fn command_contextual_enabled(child: UiNode, cmd: Command, ctx: ContextVar<bool>) -> UiNode {
1030 let mut _handle = VarHandle::dummy();
1031 let mut _wgt_handle = CommandHandle::dummy();
1032 let mut _win_handle = CommandHandle::dummy();
1033 match_node(child, move |_, op| match op {
1034 UiNodeOp::Init => {
1035 let ctx = ctx.current_context();
1036 let handle = cmd.scoped(WIDGET.id()).subscribe(ctx.get());
1037 let win_handle = if WIDGET.parent_id().is_none() {
1038 cmd.scoped(WINDOW.id()).subscribe(ctx.get())
1039 } else {
1040 CommandHandle::dummy()
1041 };
1042 if !ctx.capabilities().is_const() {
1043 let handle = handle.enabled().clone();
1044 let win_handle = win_handle.enabled().clone();
1045 _handle = ctx.hook(move |a| {
1046 handle.set(*a.value());
1047 win_handle.set(*a.value());
1048 true
1049 });
1050 }
1051 _wgt_handle = handle;
1052 _win_handle = win_handle;
1053 }
1054 UiNodeOp::Deinit => {
1055 _handle = VarHandle::dummy();
1056 _wgt_handle = CommandHandle::dummy();
1057 _win_handle = CommandHandle::dummy();
1058 }
1059 _ => {}
1060 })
1061}
1062
1063pub fn validate_getter_var<T: VarValue>(_var: &Var<T>) {
1065 #[cfg(debug_assertions)]
1066 if _var.capabilities().is_always_read_only() {
1067 tracing::error!(
1068 "`is_`, `has_` or `get_` property inited with read-only var in `{}`",
1069 WIDGET.trace_id()
1070 );
1071 }
1072}
1073
1074pub fn bind_state<T: VarValue>(child: impl IntoUiNode, source: impl IntoVar<T>, state: impl IntoVar<T>) -> UiNode {
1079 let source = source.into_var();
1080 bind_state_init(child, state, move |state| {
1081 state.set_from(&source);
1082 source.bind(state)
1083 })
1084}
1085
1086pub fn bind_state_init<T>(
1090 child: impl IntoUiNode,
1091 state: impl IntoVar<T>,
1092 mut bind: impl FnMut(&Var<T>) -> VarHandle + Send + 'static,
1093) -> UiNode
1094where
1095 T: VarValue,
1096{
1097 let state = state.into_var();
1098 let mut _binding = VarHandle::dummy();
1099
1100 match_node(child, move |_, op| match op {
1101 UiNodeOp::Init => {
1102 validate_getter_var(&state);
1103 _binding = bind(&state);
1104 }
1105 UiNodeOp::Deinit => {
1106 _binding = VarHandle::dummy();
1107 }
1108 _ => {}
1109 })
1110}
1111
1112pub fn bind_state_info<T>(
1116 child: impl IntoUiNode,
1117 state: impl IntoVar<T>,
1118 mut bind: impl FnMut(&Var<T>) -> VarHandle + Send + 'static,
1119) -> UiNode
1120where
1121 T: VarValue,
1122{
1123 let state = state.into_var();
1124 let mut _binding = VarHandle::dummy();
1125
1126 match_node(child, move |_, op| match op {
1127 UiNodeOp::Init => {
1128 let id = WINDOW.id();
1129 WIDGET.sub_event_when(&WIDGET_TREE_CHANGED_EVENT, move |a| !a.is_update && a.tree.window_id() == id);
1130 }
1131 UiNodeOp::Update { .. } => {
1132 WIDGET_TREE_CHANGED_EVENT.each_update(true, |a| {
1133 if !a.is_update && a.tree.window_id() == WINDOW.id() {
1134 _binding = bind(&state);
1135 }
1136 });
1137 }
1138 UiNodeOp::Deinit => {
1139 _binding = VarHandle::dummy();
1140 }
1141 _ => {}
1142 })
1143}
1144
1145pub fn widget_state_is_state(
1150 child: impl IntoUiNode,
1151 predicate: impl Fn(StateMapRef<WIDGET>) -> bool + Send + 'static,
1152 deinit: impl Fn(StateMapRef<WIDGET>) -> bool + Send + 'static,
1153 state: impl IntoVar<bool>,
1154) -> UiNode {
1155 let state = state.into_var();
1156
1157 match_node(child, move |child, op| match op {
1158 UiNodeOp::Init => {
1159 validate_getter_var(&state);
1160 child.init();
1161 let s = WIDGET.with_state(&predicate);
1162 if s != state.get() {
1163 state.set(s);
1164 }
1165 }
1166 UiNodeOp::Deinit => {
1167 child.deinit();
1168 let s = WIDGET.with_state(&deinit);
1169 if s != state.get() {
1170 state.set(s);
1171 }
1172 }
1173 UiNodeOp::Update { updates } => {
1174 child.update(updates);
1175 let s = WIDGET.with_state(&predicate);
1176 if s != state.get() {
1177 state.set(s);
1178 }
1179 }
1180 _ => {}
1181 })
1182}
1183
1184pub fn widget_state_get_state<T: VarValue>(
1189 child: impl IntoUiNode,
1190 get_new: impl Fn(StateMapRef<WIDGET>, &T) -> Option<T> + Send + 'static,
1191 get_deinit: impl Fn(StateMapRef<WIDGET>, &T) -> Option<T> + Send + 'static,
1192 state: impl IntoVar<T>,
1193) -> UiNode {
1194 let state = state.into_var();
1195 match_node(child, move |child, op| match op {
1196 UiNodeOp::Init => {
1197 validate_getter_var(&state);
1198 child.init();
1199 let new = state.with(|s| WIDGET.with_state(|w| get_new(w, s)));
1200 if let Some(new) = new {
1201 state.set(new);
1202 }
1203 }
1204 UiNodeOp::Deinit => {
1205 child.deinit();
1206
1207 let new = state.with(|s| WIDGET.with_state(|w| get_deinit(w, s)));
1208 if let Some(new) = new {
1209 state.set(new);
1210 }
1211 }
1212 UiNodeOp::Update { updates } => {
1213 child.update(updates);
1214 let new = state.with(|s| WIDGET.with_state(|w| get_new(w, s)));
1215 if let Some(new) = new {
1216 state.set(new);
1217 }
1218 }
1219 _ => {}
1220 })
1221}
1222
1223pub fn fill_node(content: impl IntoUiNode) -> UiNode {
1229 let mut clip_bounds = PxSize::zero();
1230 let mut clip_corners = PxCornerRadius::zero();
1231
1232 let mut offset = PxVector::zero();
1233 let offset_key = FrameValueKey::new_unique();
1234 let mut define_frame = false;
1235
1236 match_node(content, move |child, op| match op {
1237 UiNodeOp::Init => {
1238 WIDGET.sub_var_layout(&BORDER_ALIGN_VAR);
1239 define_frame = false;
1240 offset = PxVector::zero();
1241 }
1242 UiNodeOp::Measure { desired_size, .. } => {
1243 let offsets = BORDER.inner_offsets();
1244 let align = BORDER_ALIGN_VAR.get();
1245
1246 let our_offsets = offsets * align;
1247 let size_offset = offsets - our_offsets;
1248
1249 let size_increase = PxSize::new(size_offset.horizontal(), size_offset.vertical());
1250
1251 *desired_size = LAYOUT.constraints().fill_size() + size_increase;
1252 }
1253 UiNodeOp::Layout { wl, final_size } => {
1254 let (bounds, corners) = BORDER.fill_bounds();
1259
1260 let mut new_offset = bounds.origin.to_vector();
1261
1262 if clip_bounds != bounds.size || clip_corners != corners {
1263 clip_bounds = bounds.size;
1264 clip_corners = corners;
1265 WIDGET.render();
1266 }
1267
1268 let (_, branch_offset) = LAYOUT.with_constraints(PxConstraints2d::new_exact_size(bounds.size), || {
1269 wl.with_branch_child(|wl| child.layout(wl))
1270 });
1271 new_offset += branch_offset;
1272
1273 if offset != new_offset {
1274 offset = new_offset;
1275
1276 if define_frame {
1277 WIDGET.render_update();
1278 } else {
1279 define_frame = true;
1280 WIDGET.render();
1281 }
1282 }
1283
1284 *final_size = bounds.size;
1285 }
1286 UiNodeOp::Render { frame } => {
1287 let mut render = |frame: &mut FrameBuilder| {
1288 let bounds = PxRect::from_size(clip_bounds);
1289 frame.push_clips(
1290 |c| {
1291 if clip_corners != PxCornerRadius::zero() {
1292 c.push_clip_rounded_rect(bounds, clip_corners, false, false);
1293 } else {
1294 c.push_clip_rect(bounds, false, false);
1295 }
1296
1297 if let Some(inline) = WIDGET.bounds().inline() {
1298 for r in inline.negative_space().iter() {
1299 c.push_clip_rect(*r, true, false);
1300 }
1301 }
1302 },
1303 |f| child.render(f),
1304 );
1305 };
1306
1307 if define_frame {
1308 frame.push_reference_frame(offset_key.into(), offset_key.bind(offset.into(), false), true, false, |frame| {
1309 render(frame);
1310 });
1311 } else {
1312 render(frame);
1313 }
1314 }
1315 UiNodeOp::RenderUpdate { update } => {
1316 if define_frame {
1317 update.with_transform(offset_key.update(offset.into(), false), false, |update| {
1318 child.render_update(update);
1319 });
1320 } else {
1321 child.render_update(update);
1322 }
1323 }
1324 _ => {}
1325 })
1326}
1327
1328pub fn border_node(child: impl IntoUiNode, border_offsets: impl IntoVar<SideOffsets>, border_visual: impl IntoUiNode) -> UiNode {
1333 let offsets = border_offsets.into_var();
1334 let mut render_offsets = PxSideOffsets::zero();
1335 let mut border_rect = PxRect::zero();
1336
1337 match_node(ui_vec![child, border_visual], move |children, op| match op {
1338 UiNodeOp::Init => {
1339 WIDGET.sub_var_layout(&offsets).sub_var_render(&BORDER_OVER_VAR);
1340 }
1341 UiNodeOp::Measure { wm, desired_size } => {
1342 let offsets = offsets.layout();
1343 *desired_size = BORDER.measure_border(offsets, || {
1344 LAYOUT.with_sub_size(PxSize::new(offsets.horizontal(), offsets.vertical()), || {
1345 children.node().with_child(0, |n| wm.measure_block(n))
1346 })
1347 });
1348 children.delegated();
1349 }
1350 UiNodeOp::Layout { wl, final_size } => {
1351 let offsets = offsets.layout();
1359 if render_offsets != offsets {
1360 render_offsets = offsets;
1361 WIDGET.render();
1362 }
1363
1364 let parent_offsets = BORDER.inner_offsets();
1365 let origin = PxPoint::new(parent_offsets.left, parent_offsets.top);
1366 if border_rect.origin != origin {
1367 border_rect.origin = origin;
1368 WIDGET.render();
1369 }
1370
1371 BORDER.layout_border(offsets, || {
1373 wl.translate(PxVector::new(offsets.left, offsets.top));
1374
1375 let taken_size = PxSize::new(offsets.horizontal(), offsets.vertical());
1376 border_rect.size = LAYOUT.with_sub_size(taken_size, || children.node().with_child(0, |n| n.layout(wl)));
1377
1378 LAYOUT.with_constraints(PxConstraints2d::new_exact_size(border_rect.size), || {
1380 BORDER.with_border_layout(border_rect, offsets, || {
1381 children.node().with_child(1, |n| n.layout(wl));
1382 });
1383 });
1384 });
1385 children.delegated();
1386
1387 *final_size = border_rect.size;
1388 }
1389 UiNodeOp::Render { frame } => {
1390 if BORDER_OVER_VAR.get() {
1391 children.node().with_child(0, |c| c.render(frame));
1392 BORDER.with_border_layout(border_rect, render_offsets, || {
1393 children.node().with_child(1, |c| c.render(frame));
1394 });
1395 } else {
1396 BORDER.with_border_layout(border_rect, render_offsets, || {
1397 children.node().with_child(1, |c| c.render(frame));
1398 });
1399 children.node().with_child(0, |c| c.render(frame));
1400 }
1401 children.delegated();
1402 }
1403 UiNodeOp::RenderUpdate { update } => {
1404 children.node().with_child(0, |c| c.render_update(update));
1405 BORDER.with_border_layout(border_rect, render_offsets, || {
1406 children.node().with_child(1, |c| c.render_update(update));
1407 });
1408 children.delegated();
1409 }
1410 _ => {}
1411 })
1412}
1413
1414pub fn with_context_local<T: Any + Send + Sync + 'static>(
1420 child: impl IntoUiNode,
1421 context: &'static ContextLocal<T>,
1422 value: impl Into<T>,
1423) -> UiNode {
1424 let mut value = Some(Arc::new(value.into()));
1425
1426 match_node(child, move |child, op| {
1427 context.with_context(&mut value, || child.op(op));
1428 })
1429}
1430
1431pub fn with_context_local_init<T: Any + Send + Sync + 'static>(
1440 child: impl IntoUiNode,
1441 context: &'static ContextLocal<T>,
1442 init_value: impl FnMut() -> T + Send + 'static,
1443) -> UiNode {
1444 with_context_local_init_impl(child.into_node(), context, init_value)
1445}
1446fn with_context_local_init_impl<T: Any + Send + Sync + 'static>(
1447 child: UiNode,
1448 context: &'static ContextLocal<T>,
1449 mut init_value: impl FnMut() -> T + Send + 'static,
1450) -> UiNode {
1451 let mut value = None;
1452
1453 match_node(child, move |child, op| {
1454 let mut is_deinit = false;
1455 match &op {
1456 UiNodeOp::Init => {
1457 value = Some(Arc::new(init_value()));
1458 }
1459 UiNodeOp::Deinit => {
1460 is_deinit = true;
1461 }
1462 _ => {}
1463 }
1464
1465 context.with_context(&mut value, || child.op(op));
1466
1467 if is_deinit {
1468 value = None;
1469 }
1470 })
1471}
1472
1473pub fn with_context_blend(mut ctx: LocalContext, over: bool, child: impl IntoUiNode) -> UiNode {
1502 match_widget(child, move |c, op| {
1503 if let UiNodeOp::Init = op {
1504 let init_app = LocalContext::current_app();
1505 ctx.with_context_blend(over, || {
1506 let ctx_app = LocalContext::current_app();
1507 assert_eq!(init_app, ctx_app);
1508 c.op(op)
1509 });
1510 } else {
1511 ctx.with_context_blend(over, || c.op(op));
1512 }
1513 })
1514}
1515
1516pub fn with_widget_state<U, I, T>(child: U, id: impl Into<StateId<T>>, default: I, value: impl IntoVar<T>) -> UiNode
1558where
1559 U: IntoUiNode,
1560 I: Fn() -> T + Send + 'static,
1561 T: StateValue + VarValue,
1562{
1563 with_widget_state_impl(child.into_node(), id.into(), default, value.into_var())
1564}
1565fn with_widget_state_impl<I, T>(child: UiNode, id: impl Into<StateId<T>>, default: I, value: impl IntoVar<T>) -> UiNode
1566where
1567 I: Fn() -> T + Send + 'static,
1568 T: StateValue + VarValue,
1569{
1570 let id = id.into();
1571 let value = value.into_var();
1572
1573 match_node(child, move |child, op| match op {
1574 UiNodeOp::Init => {
1575 child.init();
1576 WIDGET.sub_var(&value);
1577 WIDGET.set_state(id, value.get());
1578 }
1579 UiNodeOp::Deinit => {
1580 child.deinit();
1581 WIDGET.set_state(id, default());
1582 }
1583 UiNodeOp::Update { updates } => {
1584 child.update(updates);
1585 if let Some(v) = value.get_new() {
1586 WIDGET.set_state(id, v);
1587 }
1588 }
1589 _ => {}
1590 })
1591}
1592
1593pub fn with_widget_state_modify<U, S, V, I, M>(child: U, id: impl Into<StateId<S>>, value: impl IntoVar<V>, default: I, modify: M) -> UiNode
1601where
1602 U: IntoUiNode,
1603 S: StateValue,
1604 V: VarValue,
1605 I: Fn() -> S + Send + 'static,
1606 M: FnMut(&mut S, &V) + Send + 'static,
1607{
1608 with_widget_state_modify_impl(child.into_node(), id.into(), value.into_var(), default, modify)
1609}
1610fn with_widget_state_modify_impl<S, V, I, M>(
1611 child: UiNode,
1612 id: impl Into<StateId<S>>,
1613 value: impl IntoVar<V>,
1614 default: I,
1615 mut modify: M,
1616) -> UiNode
1617where
1618 S: StateValue,
1619 V: VarValue,
1620 I: Fn() -> S + Send + 'static,
1621 M: FnMut(&mut S, &V) + Send + 'static,
1622{
1623 let id = id.into();
1624 let value = value.into_var();
1625
1626 match_node(child, move |child, op| match op {
1627 UiNodeOp::Init => {
1628 child.init();
1629
1630 WIDGET.sub_var(&value);
1631
1632 value.with(|v| {
1633 WIDGET.with_state_mut(|mut s| {
1634 modify(s.entry(id).or_insert_with(&default), v);
1635 })
1636 })
1637 }
1638 UiNodeOp::Deinit => {
1639 child.deinit();
1640
1641 WIDGET.set_state(id, default());
1642 }
1643 UiNodeOp::Update { updates } => {
1644 child.update(updates);
1645 value.with_new(|v| {
1646 WIDGET.with_state_mut(|mut s| {
1647 modify(s.req_mut(id), v);
1648 })
1649 });
1650 }
1651 _ => {}
1652 })
1653}
1654
1655pub fn interactive_node(child: impl IntoUiNode, interactive: impl IntoVar<bool>) -> UiNode {
1667 let interactive = interactive.into_var();
1668
1669 match_node(child, move |child, op| match op {
1670 UiNodeOp::Init => {
1671 WIDGET.sub_var_info(&interactive);
1672 }
1673 UiNodeOp::Info { info } => {
1674 if interactive.get() {
1675 child.info(info);
1676 } else if let Some(mut wgt) = child.node().as_widget() {
1677 let id = wgt.id();
1678 info.push_interactivity_filter(move |args| {
1680 if args.info.id() == id {
1681 Interactivity::BLOCKED
1682 } else {
1683 Interactivity::ENABLED
1684 }
1685 });
1686 child.info(info);
1687 } else {
1688 let block_range = info.with_children_range(|info| child.info(info));
1689 if !block_range.is_empty() {
1690 let id = WIDGET.id();
1693 info.push_interactivity_filter(move |args| {
1694 if let Some(parent) = args.info.parent()
1695 && parent.id() == id
1696 {
1697 for (i, item) in parent.children().enumerate() {
1699 if item == args.info {
1700 return if !block_range.contains(&i) {
1701 Interactivity::ENABLED
1702 } else {
1703 Interactivity::BLOCKED
1704 };
1705 } else if i >= block_range.end {
1706 break;
1707 }
1708 }
1709 }
1710 Interactivity::ENABLED
1711 });
1712 }
1713 }
1714 }
1715 _ => {}
1716 })
1717}
1718
1719pub fn with_index_node(
1723 child: impl IntoUiNode,
1724 panel_list_id: impl Into<StateId<PanelListRange>>,
1725 mut update: impl FnMut(Option<usize>) + Send + 'static,
1726) -> UiNode {
1727 let panel_list_id = panel_list_id.into();
1728 let mut version = None;
1729 match_node(child, move |_, op| match op {
1730 UiNodeOp::Deinit => {
1731 update(None);
1732 version = None;
1733 }
1734 UiNodeOp::Update { .. } => {
1735 let info = WIDGET.info();
1737 if let Some(parent) = info.parent()
1738 && let Some(mut c) = PanelListRange::update(&parent, panel_list_id, &mut version)
1739 {
1740 let id = info.id();
1741 let p = c.position(|w| w.id() == id);
1742 update(p);
1743 }
1744 }
1745 _ => {}
1746 })
1747}
1748
1749pub fn with_rev_index_node(
1753 child: impl IntoUiNode,
1754 panel_list_id: impl Into<StateId<PanelListRange>>,
1755 mut update: impl FnMut(Option<usize>) + Send + 'static,
1756) -> UiNode {
1757 let panel_list_id = panel_list_id.into();
1758 let mut version = None;
1759 match_node(child, move |_, op| match op {
1760 UiNodeOp::Deinit => {
1761 update(None);
1762 version = None;
1763 }
1764 UiNodeOp::Update { .. } => {
1765 let info = WIDGET.info();
1766 if let Some(parent) = info.parent()
1767 && let Some(c) = PanelListRange::update(&parent, panel_list_id, &mut version)
1768 {
1769 let id = info.id();
1770 let p = c.rev().position(|w| w.id() == id);
1771 update(p);
1772 }
1773 }
1774 _ => {}
1775 })
1776}
1777
1778pub fn with_index_len_node(
1785 child: impl IntoUiNode,
1786 panel_list_id: impl Into<StateId<PanelListRange>>,
1787 mut update: impl FnMut(Option<(usize, usize)>) + Send + 'static,
1788) -> UiNode {
1789 let panel_list_id = panel_list_id.into();
1790 let mut version = None;
1791 match_node(child, move |_, op| match op {
1792 UiNodeOp::Deinit => {
1793 update(None);
1794 version = None;
1795 }
1796 UiNodeOp::Update { .. } => {
1797 let info = WIDGET.info();
1798 if let Some(parent) = info.parent()
1799 && let Some(mut iter) = PanelListRange::update(&parent, panel_list_id, &mut version)
1800 {
1801 let id = info.id();
1802 let mut p = 0;
1803 let mut count = 0;
1804 for c in &mut iter {
1805 if c.id() == id {
1806 p = count;
1807 count += 1 + iter.count();
1808 break;
1809 } else {
1810 count += 1;
1811 }
1812 }
1813 update(Some((p, count)));
1814 }
1815 }
1816 _ => {}
1817 })
1818}
1819
1820pub fn presenter<D: VarValue>(data: impl IntoVar<D>, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1833 Presenter {
1834 data: data.into_var(),
1835 wgt_fn: wgt_fn.into_var(),
1836 child: UiNode::nil(),
1837 }
1838 .into_node()
1839}
1840
1841pub fn presenter_opt<D: VarValue>(data: impl IntoVar<Option<D>>, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1847 presenter(
1848 data,
1849 wgt_fn.into_var().map(|w_fn| {
1850 crate::wgt_fn!(w_fn, |d| match d {
1851 Some(d) => w_fn(d),
1852 None => UiNode::nil(),
1853 })
1854 }),
1855 )
1856}
1857
1858pub fn list_presenter<D: VarValue>(list: impl IntoVar<ObservableVec<D>>, item_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1864 ListPresenter {
1865 list: list.into_var(),
1866 item_fn: item_fn.into_var(),
1867 view: ui_vec![],
1868 }
1869 .into_node()
1870}
1871
1872pub fn list_presenter_from_iter<D, L>(list: impl IntoVar<L>, item_fn: impl IntoVar<WidgetFn<D>>) -> UiNode
1878where
1879 D: VarValue,
1880 L: IntoIterator<Item = D> + VarValue,
1881{
1882 ListPresenterFromIter {
1883 list: list.into_var(),
1884 item_fn: item_fn.into_var(),
1885 view: ui_vec![],
1886 }
1887 .into_node()
1888}
1889
1890pub fn list_presenter_from_node<D>(list: impl IntoVar<D>, list_fn: impl IntoVar<WidgetFn<D>>) -> UiNode
1894where
1895 D: VarValue,
1896{
1897 Presenter {
1898 data: list.into_var(),
1899 wgt_fn: list_fn.into_var(),
1900 child: ui_vec![].into_node(),
1901 }
1902 .into_node()
1903}
1904
1905struct Presenter<D>
1906where
1907 D: VarValue,
1908{
1909 data: Var<D>,
1910 wgt_fn: Var<WidgetFn<D>>,
1911 child: UiNode,
1912}
1913impl<D> Presenter<D>
1914where
1915 D: VarValue,
1916{
1917 fn on_update(&mut self) -> bool {
1918 if self.data.is_new() || self.wgt_fn.is_new() {
1919 let was_list = self.child.is_list();
1920
1921 self.child.deinit();
1922
1923 let new_child = self.wgt_fn.get()(self.data.get());
1924 if was_list {
1925 if !new_child.is_list() {
1926 #[cfg(debug_assertions)]
1927 tracing::warn!("presenter changed to !is_list, will convert to list");
1928 }
1929 self.child = new_child.into_list();
1930 } else {
1931 #[cfg(debug_assertions)]
1932 if self.child.is_list() {
1933 tracing::warn!("presenter changed to is_list, likely only first entry node will be used");
1934 }
1935 self.child = new_child;
1936 }
1937
1938 self.child.init();
1939 WIDGET.update_info().layout().render();
1940 true
1941 } else {
1942 false
1943 }
1944 }
1945}
1946impl<D> UiNodeImpl for Presenter<D>
1947where
1948 D: VarValue,
1949{
1950 fn children_len(&self) -> usize {
1951 self.child.children_len()
1952 }
1953
1954 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
1955 self.child.with_child(index, visitor)
1956 }
1957
1958 fn is_list(&self) -> bool {
1959 self.child.is_list()
1960 }
1961
1962 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
1963 self.child.as_dyn().for_each_child(visitor);
1964 }
1965
1966 fn try_for_each_child(
1967 &mut self,
1968 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<BoxAnyVarValue>,
1969 ) -> std::ops::ControlFlow<BoxAnyVarValue> {
1970 self.child.as_dyn().try_for_each_child(visitor)
1971 }
1972
1973 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
1974 self.child.as_dyn().par_each_child(visitor);
1975 }
1976
1977 fn par_fold_reduce(
1978 &mut self,
1979 identity: BoxAnyVarValue,
1980 fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
1981 reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
1982 ) -> BoxAnyVarValue {
1983 self.child.as_dyn().par_fold_reduce(identity, fold, reduce)
1984 }
1985
1986 fn init(&mut self) {
1987 WIDGET.sub_var(&self.data).sub_var(&self.wgt_fn);
1988 self.child = self.wgt_fn.get()(self.data.get());
1989 self.child.init();
1990 }
1991
1992 fn deinit(&mut self) {
1993 self.child.deinit();
1994 if self.child.is_list() {
1995 self.child = ui_vec![].into_node();
1996 } else {
1997 self.child = UiNode::nil();
1998 }
1999 }
2000
2001 fn info(&mut self, info: &mut zng_app::widget::info::WidgetInfoBuilder) {
2002 self.child.info(info);
2003 }
2004
2005 fn update(&mut self, updates: &WidgetUpdates) {
2006 if !self.on_update() {
2007 self.child.update(updates);
2008 }
2009 }
2010
2011 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
2012 if self.on_update() {
2013 observer.reset();
2014 } else {
2015 self.child.as_dyn().update_list(updates, observer);
2016 }
2017 }
2018
2019 fn measure(&mut self, wm: &mut zng_app::widget::info::WidgetMeasure) -> PxSize {
2020 self.child.as_dyn().measure(wm)
2021 }
2022
2023 fn measure_list(
2024 &mut self,
2025 wm: &mut zng_app::widget::info::WidgetMeasure,
2026 measure: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetMeasure) -> PxSize + Sync),
2027 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2028 ) -> PxSize {
2029 self.child.as_dyn().measure_list(wm, measure, fold_size)
2030 }
2031
2032 fn layout(&mut self, wl: &mut zng_app::widget::info::WidgetLayout) -> PxSize {
2033 self.child.as_dyn().layout(wl)
2034 }
2035
2036 fn layout_list(
2037 &mut self,
2038 wl: &mut zng_app::widget::info::WidgetLayout,
2039 layout: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetLayout) -> PxSize + Sync),
2040 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2041 ) -> PxSize {
2042 self.child.as_dyn().layout_list(wl, layout, fold_size)
2043 }
2044
2045 fn render(&mut self, frame: &mut FrameBuilder) {
2046 self.child.as_dyn().render(frame);
2047 }
2048
2049 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
2050 self.child.as_dyn().render_list(frame, render);
2051 }
2052
2053 fn render_update(&mut self, update: &mut zng_app::render::FrameUpdate) {
2054 self.child.as_dyn().render_update(update);
2055 }
2056
2057 fn render_update_list(
2058 &mut self,
2059 update: &mut zng_app::render::FrameUpdate,
2060 render_update: &(dyn Fn(usize, &mut UiNode, &mut zng_app::render::FrameUpdate) + Sync),
2061 ) {
2062 self.child.as_dyn().render_update_list(update, render_update);
2063 }
2064
2065 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2066 self.child.as_dyn().as_widget()
2067 }
2068}
2069
2070struct ListPresenter<D>
2071where
2072 D: VarValue,
2073{
2074 list: Var<ObservableVec<D>>,
2075 item_fn: Var<WidgetFn<D>>,
2076 view: UiVec,
2077}
2078
2079impl<D> UiNodeImpl for ListPresenter<D>
2080where
2081 D: VarValue,
2082{
2083 fn children_len(&self) -> usize {
2084 self.view.len()
2085 }
2086
2087 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
2088 self.view.with_child(index, visitor)
2089 }
2090
2091 fn is_list(&self) -> bool {
2092 true
2093 }
2094
2095 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
2096 self.view.for_each_child(visitor);
2097 }
2098
2099 fn try_for_each_child(
2100 &mut self,
2101 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<BoxAnyVarValue>,
2102 ) -> std::ops::ControlFlow<BoxAnyVarValue> {
2103 self.view.try_for_each_child(visitor)
2104 }
2105
2106 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
2107 self.view.par_each_child(visitor);
2108 }
2109
2110 fn par_fold_reduce(
2111 &mut self,
2112 identity: BoxAnyVarValue,
2113 fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
2114 reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
2115 ) -> BoxAnyVarValue {
2116 self.view.par_fold_reduce(identity, fold, reduce)
2117 }
2118
2119 fn init(&mut self) {
2120 debug_assert!(self.view.is_empty());
2121 self.view.clear();
2122
2123 WIDGET.sub_var(&self.list).sub_var(&self.item_fn);
2124
2125 let e_fn = self.item_fn.get();
2126 self.list.with(|l| {
2127 for el in l.iter() {
2128 let child = e_fn(el.clone());
2129 self.view.push(child);
2130 }
2131 });
2132
2133 self.view.init();
2134 }
2135
2136 fn deinit(&mut self) {
2137 self.view.deinit();
2138 self.view.clear();
2139 }
2140
2141 fn update(&mut self, updates: &WidgetUpdates) {
2142 self.update_list(updates, &mut ());
2143 }
2144
2145 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
2146 let mut need_reset = self.item_fn.is_new();
2147
2148 let is_new = self
2149 .list
2150 .with_new(|l| {
2151 need_reset |= l.changes().is_empty() || l.changes() == [VecChange::Clear];
2152
2153 if need_reset {
2154 return;
2155 }
2156
2157 self.view.update_list(updates, observer);
2159
2160 let e_fn = self.item_fn.get();
2161
2162 for change in l.changes() {
2163 match change {
2164 VecChange::Insert { index, count } => {
2165 for i in *index..(*index + count) {
2166 let mut el = e_fn(l[i].clone());
2167 el.init();
2168 self.view.insert(i, el);
2169 observer.inserted(i);
2170 }
2171 }
2172 VecChange::Remove { index, count } => {
2173 let mut count = *count;
2174 let index = *index;
2175 while count > 0 {
2176 count -= 1;
2177
2178 let mut el = self.view.remove(index);
2179 el.deinit();
2180 observer.removed(index);
2181 }
2182 }
2183 VecChange::Move { from_index, to_index } => {
2184 let el = self.view.remove(*from_index);
2185 self.view.insert(*to_index, el);
2186 observer.moved(*from_index, *to_index);
2187 }
2188 VecChange::Clear => unreachable!(),
2189 }
2190 }
2191 })
2192 .is_some();
2193
2194 if !need_reset && !is_new && self.list.with(|l| l.len() != self.view.len()) {
2195 need_reset = true;
2196 }
2197
2198 if need_reset {
2199 self.view.deinit();
2200 self.view.clear();
2201
2202 let e_fn = self.item_fn.get();
2203 self.list.with(|l| {
2204 for el in l.iter() {
2205 let child = e_fn(el.clone());
2206 self.view.push(child);
2207 }
2208 });
2209
2210 self.view.init();
2211 } else if !is_new {
2212 self.view.update_list(updates, observer);
2213 }
2214 }
2215
2216 fn info(&mut self, info: &mut zng_app::widget::info::WidgetInfoBuilder) {
2217 self.view.info(info);
2218 }
2219
2220 fn measure(&mut self, wm: &mut zng_app::widget::info::WidgetMeasure) -> PxSize {
2221 self.view.measure(wm)
2222 }
2223
2224 fn measure_list(
2225 &mut self,
2226 wm: &mut zng_app::widget::info::WidgetMeasure,
2227 measure: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetMeasure) -> PxSize + Sync),
2228 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2229 ) -> PxSize {
2230 self.view.measure_list(wm, measure, fold_size)
2231 }
2232
2233 fn layout(&mut self, wl: &mut zng_app::widget::info::WidgetLayout) -> PxSize {
2234 self.view.layout(wl)
2235 }
2236
2237 fn layout_list(
2238 &mut self,
2239 wl: &mut zng_app::widget::info::WidgetLayout,
2240 layout: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetLayout) -> PxSize + Sync),
2241 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2242 ) -> PxSize {
2243 self.view.layout_list(wl, layout, fold_size)
2244 }
2245
2246 fn render(&mut self, frame: &mut FrameBuilder) {
2247 self.view.render(frame);
2248 }
2249
2250 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
2251 self.view.render_list(frame, render);
2252 }
2253
2254 fn render_update(&mut self, update: &mut zng_app::render::FrameUpdate) {
2255 self.view.render_update(update);
2256 }
2257
2258 fn render_update_list(
2259 &mut self,
2260 update: &mut zng_app::render::FrameUpdate,
2261 render_update: &(dyn Fn(usize, &mut UiNode, &mut zng_app::render::FrameUpdate) + Sync),
2262 ) {
2263 self.view.render_update_list(update, render_update);
2264 }
2265
2266 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2267 None
2268 }
2269}
2270
2271struct ListPresenterFromIter<D, L>
2272where
2273 D: VarValue,
2274 L: IntoIterator<Item = D> + VarValue,
2275{
2276 list: Var<L>,
2277 item_fn: Var<WidgetFn<D>>,
2278 view: UiVec,
2279}
2280
2281impl<D, L> UiNodeImpl for ListPresenterFromIter<D, L>
2282where
2283 D: VarValue,
2284 L: IntoIterator<Item = D> + VarValue,
2285{
2286 fn children_len(&self) -> usize {
2287 self.view.len()
2288 }
2289
2290 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
2291 self.view.with_child(index, visitor)
2292 }
2293
2294 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
2295 self.view.for_each_child(visitor)
2296 }
2297
2298 fn try_for_each_child(
2299 &mut self,
2300 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<BoxAnyVarValue>,
2301 ) -> std::ops::ControlFlow<BoxAnyVarValue> {
2302 self.view.try_for_each_child(visitor)
2303 }
2304
2305 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
2306 self.view.par_each_child(visitor);
2307 }
2308
2309 fn par_fold_reduce(
2310 &mut self,
2311 identity: BoxAnyVarValue,
2312 fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
2313 reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
2314 ) -> BoxAnyVarValue {
2315 self.view.par_fold_reduce(identity, fold, reduce)
2316 }
2317
2318 fn is_list(&self) -> bool {
2319 true
2320 }
2321
2322 fn init(&mut self) {
2323 debug_assert!(self.view.is_empty());
2324 self.view.clear();
2325
2326 WIDGET.sub_var(&self.list).sub_var(&self.item_fn);
2327
2328 let e_fn = self.item_fn.get();
2329
2330 self.view.extend(self.list.get().into_iter().map(&*e_fn));
2331 self.view.init();
2332 }
2333
2334 fn deinit(&mut self) {
2335 self.view.deinit();
2336 self.view.clear();
2337 }
2338
2339 fn update(&mut self, updates: &WidgetUpdates) {
2340 self.update_list(updates, &mut ())
2341 }
2342 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
2343 if self.list.is_new() || self.item_fn.is_new() {
2344 self.view.deinit();
2345 self.view.clear();
2346 let e_fn = self.item_fn.get();
2347 self.view.extend(self.list.get().into_iter().map(&*e_fn));
2348 self.view.init();
2349 observer.reset();
2350 } else {
2351 self.view.update_list(updates, observer);
2352 }
2353 }
2354
2355 fn info(&mut self, info: &mut zng_app::widget::info::WidgetInfoBuilder) {
2356 self.view.info(info)
2357 }
2358
2359 fn measure(&mut self, wm: &mut zng_app::widget::info::WidgetMeasure) -> PxSize {
2360 self.view.measure(wm)
2361 }
2362
2363 fn measure_list(
2364 &mut self,
2365 wm: &mut zng_app::widget::info::WidgetMeasure,
2366 measure: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetMeasure) -> PxSize + Sync),
2367 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2368 ) -> PxSize {
2369 self.view.measure_list(wm, measure, fold_size)
2370 }
2371
2372 fn layout(&mut self, wl: &mut zng_app::widget::info::WidgetLayout) -> PxSize {
2373 self.view.layout(wl)
2374 }
2375
2376 fn layout_list(
2377 &mut self,
2378 wl: &mut zng_app::widget::info::WidgetLayout,
2379 layout: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetLayout) -> PxSize + Sync),
2380 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2381 ) -> PxSize {
2382 self.view.layout_list(wl, layout, fold_size)
2383 }
2384
2385 fn render(&mut self, frame: &mut FrameBuilder) {
2386 self.view.render(frame);
2387 }
2388
2389 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
2390 self.view.render_list(frame, render);
2391 }
2392
2393 fn render_update(&mut self, update: &mut zng_app::render::FrameUpdate) {
2394 self.view.render_update(update);
2395 }
2396
2397 fn render_update_list(
2398 &mut self,
2399 update: &mut zng_app::render::FrameUpdate,
2400 render_update: &(dyn Fn(usize, &mut UiNode, &mut zng_app::render::FrameUpdate) + Sync),
2401 ) {
2402 self.view.render_update_list(update, render_update);
2403 }
2404
2405 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2406 None
2407 }
2408}
2409
2410pub trait VarPresent<D: VarValue> {
2412 fn present(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2414}
2415impl<D: VarValue> VarPresent<D> for Var<D> {
2416 fn present(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2417 presenter(self.clone(), wgt_fn)
2418 }
2419}
2420
2421pub trait VarPresentOpt<D: VarValue> {
2423 fn present_opt(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2425}
2426impl<D: VarValue> VarPresentOpt<D> for Var<Option<D>> {
2427 fn present_opt(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2428 presenter_opt(self.clone(), wgt_fn)
2429 }
2430}
2431
2432pub trait VarPresentList<D: VarValue> {
2434 fn present_list(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2436}
2437impl<D: VarValue> VarPresentList<D> for Var<ObservableVec<D>> {
2438 fn present_list(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2439 list_presenter(self.clone(), wgt_fn)
2440 }
2441}
2442
2443pub trait VarPresentListFromIter<D: VarValue, L: IntoIterator<Item = D> + VarValue> {
2445 fn present_list_from_iter(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2447}
2448impl<D: VarValue, L: IntoIterator<Item = D> + VarValue> VarPresentListFromIter<D, L> for Var<L> {
2449 fn present_list_from_iter(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2450 list_presenter_from_iter(self.clone(), wgt_fn)
2451 }
2452}
2453
2454pub trait VarPresentListFromNode<L: VarValue> {
2456 fn present_list_from_node(&self, list_fn: impl IntoVar<WidgetFn<L>>) -> UiNode;
2458}
2459impl<L: VarValue> VarPresentListFromNode<L> for Var<L> {
2460 fn present_list_from_node(&self, list_fn: impl IntoVar<WidgetFn<L>>) -> UiNode {
2461 list_presenter_from_node(self.clone(), list_fn)
2462 }
2463}
2464
2465pub trait VarPresentData<D: VarValue> {
2467 fn present_data(&self, data: impl IntoVar<D>) -> UiNode;
2469}
2470impl<D: VarValue> VarPresentData<D> for Var<WidgetFn<D>> {
2471 fn present_data(&self, data: impl IntoVar<D>) -> UiNode {
2472 presenter(data, self.clone())
2473 }
2474}