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,
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 $(#[$meta:meta])+
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 $(#[$meta])+
806 $vis fn $on_ident$(<$on_pre_ident $(, $can_ident)?>)?($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
807 $COMMAND
808 }
809 }
810 )+};
811}
812#[doc(inline)]
813pub use command_property;
814#[doc(hidden)]
815#[macro_export]
816macro_rules! command_property_impl {
817 (
818 $(#[$meta:meta])+
819 $vis:vis fn $on_ident:ident < $on_pre_ident:ident, $can_ident:ident> (
820 $child:ident: impl $IntoUiNode:path,
821 $handler:ident: $Handler:ty
822 ) -> $UiNode:path {
823 $COMMAND:path
824 }
825 ) => {
826 $crate::node::paste! {
827 $crate::node::__macro_util::context_var! {
828 #[doc = concat!("[`", stringify!($on_ident), "`](fn@", stringify!($on_ident), ")")]
830 #[doc = concat!("[`", stringify!($on_pre_ident), "`](fn@", stringify!($on_pre_ident), ")")]
832 #[doc = concat!("[`", stringify!($can_ident), "`](fn@", stringify!($can_ident), ")")]
836 $vis static [<$can_ident:upper _VAR>]: bool = true;
838 }
839
840 #[doc = concat!("[`", stringify!($on_ident), "`](fn@", stringify!($on_ident), ")")]
842 #[doc = concat!("[`", stringify!($on_pre_ident), "`](fn@", stringify!($on_pre_ident), ")")]
844 #[doc = "Sets the [`"$can_ident:upper "_VAR`]."]
847 $vis fn $can_ident(
848 child: impl $crate::node::__macro_util::IntoUiNode,
849 enabled: impl $crate::node::__macro_util::IntoVar<bool>,
850 ) -> $crate::node::__macro_util::UiNode {
851 $crate::node::with_context_var(child, self::[<$can_ident:upper _VAR>], enabled)
852 }
853
854 $crate::event_property! {
855 $(#[$meta])+
856 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
861 #[doc = concat!("[`", stringify!($can_ident), "`](fn@", stringify!($can_ident), ")")]
866 $vis fn $on_ident<$on_pre_ident>($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
868 const PRE: bool;
869 let child = $crate::node::EventNodeBuilder::new(*$COMMAND)
870 .filter(|| {
871 let enabled = self::[<$can_ident:upper _VAR>].current_context();
872 move |_| enabled.get()
873 })
874 .build::<PRE>($child, $handler);
875 $crate::node::command_contextual_enabled(child, $COMMAND, [<$can_ident:upper _VAR>])
876 }
877 }
878 }
879 };
880 (
881 $(#[$meta:meta])+
882 $vis:vis fn $on_ident:ident< $on_pre_ident:ident> (
883 $child:ident: impl $IntoUiNode:path,
884 $handler:ident: $Handler:ty
885 ) -> $UiNode:path {
886 $COMMAND:path
887 }
888 ) => {
889 $crate::event_property! {
890 $(#[$meta])+
891 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
896 $vis fn $on_ident<$on_pre_ident>($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
901 const PRE: bool;
902 let child = $crate::node::EventNodeBuilder::new(*$COMMAND).build::<PRE>($child, $handler);
903 $crate::node::command_always_enabled(child, $COMMAND)
904 }
905 }
906 };
907 (
908 $(#[$meta:meta])+
909 $vis:vis fn $on_ident:ident (
910 $child:ident: impl $IntoUiNode:path,
911 $handler:ident: $Handler:ty
912 ) -> $UiNode:path {
913 $COMMAND:path
914 }
915 ) => {
916 $crate::event_property! {
917 $(#[$meta])+
918 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
923 $vis fn $on_ident($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
928 let child = $crate::node::EventNodeBuilder::new(*$COMMAND).build::<false>($child, $handler);
929 $crate::node::command_always_enabled(child, $COMMAND)
930 }
931 }
932 };
933}
934
935fn validate_cmd(cmd: Command) {
936 if !matches!(cmd.scope(), CommandScope::App) {
937 tracing::error!("command for command property cannot be scoped, {cmd:?} scope will be ignored");
938 }
939}
940
941#[doc(hidden)]
942pub fn command_always_enabled(child: UiNode, cmd: Command) -> UiNode {
943 let mut _wgt_handle = CommandHandle::dummy();
944 let mut _win_handle = CommandHandle::dummy();
945 match_node(child, move |_, op| match op {
946 UiNodeOp::Init => {
947 validate_cmd(cmd);
948 _wgt_handle = cmd.scoped(WIDGET.id()).subscribe(true);
949 if WIDGET.parent_id().is_none() {
950 _win_handle = cmd.scoped(WINDOW.id()).subscribe(true);
951 }
952 }
953 UiNodeOp::Deinit => {
954 _wgt_handle = CommandHandle::dummy();
955 _win_handle = CommandHandle::dummy();
956 }
957 _ => {}
958 })
959}
960
961#[doc(hidden)]
962pub fn command_contextual_enabled(child: UiNode, cmd: Command, ctx: ContextVar<bool>) -> UiNode {
963 let mut _handle = VarHandle::dummy();
964 let mut _wgt_handle = CommandHandle::dummy();
965 let mut _win_handle = CommandHandle::dummy();
966 match_node(child, move |_, op| match op {
967 UiNodeOp::Init => {
968 let ctx = ctx.current_context();
969 let handle = cmd.scoped(WIDGET.id()).subscribe(ctx.get());
970 let win_handle = if WIDGET.parent_id().is_none() {
971 cmd.scoped(WINDOW.id()).subscribe(ctx.get())
972 } else {
973 CommandHandle::dummy()
974 };
975 if !ctx.capabilities().is_const() {
976 let _handle = ctx.hook(move |a| {
977 handle.enabled().set(*a.value());
978 win_handle.enabled().set(*a.value());
979 true
980 });
981 } else {
982 _wgt_handle = handle;
983 _win_handle = win_handle;
984 }
985 }
986 UiNodeOp::Deinit => {
987 _handle = VarHandle::dummy();
988 _wgt_handle = CommandHandle::dummy();
989 _win_handle = CommandHandle::dummy();
990 }
991 _ => {}
992 })
993}
994
995pub fn validate_getter_var<T: VarValue>(_var: &Var<T>) {
997 #[cfg(debug_assertions)]
998 if _var.capabilities().is_always_read_only() {
999 tracing::error!(
1000 "`is_`, `has_` or `get_` property inited with read-only var in `{}`",
1001 WIDGET.trace_id()
1002 );
1003 }
1004}
1005
1006pub fn bind_state<T: VarValue>(child: impl IntoUiNode, source: impl IntoVar<T>, state: impl IntoVar<T>) -> UiNode {
1011 let source = source.into_var();
1012 bind_state_init(child, state, move |state| {
1013 state.set_from(&source);
1014 source.bind(state)
1015 })
1016}
1017
1018pub fn bind_state_init<T>(
1022 child: impl IntoUiNode,
1023 state: impl IntoVar<T>,
1024 mut bind: impl FnMut(&Var<T>) -> VarHandle + Send + 'static,
1025) -> UiNode
1026where
1027 T: VarValue,
1028{
1029 let state = state.into_var();
1030 let mut _binding = VarHandle::dummy();
1031
1032 match_node(child, move |_, op| match op {
1033 UiNodeOp::Init => {
1034 validate_getter_var(&state);
1035 _binding = bind(&state);
1036 }
1037 UiNodeOp::Deinit => {
1038 _binding = VarHandle::dummy();
1039 }
1040 _ => {}
1041 })
1042}
1043
1044pub fn widget_state_is_state(
1049 child: impl IntoUiNode,
1050 predicate: impl Fn(StateMapRef<WIDGET>) -> bool + Send + 'static,
1051 deinit: impl Fn(StateMapRef<WIDGET>) -> bool + Send + 'static,
1052 state: impl IntoVar<bool>,
1053) -> UiNode {
1054 let state = state.into_var();
1055
1056 match_node(child, move |child, op| match op {
1057 UiNodeOp::Init => {
1058 validate_getter_var(&state);
1059 child.init();
1060 let s = WIDGET.with_state(&predicate);
1061 if s != state.get() {
1062 state.set(s);
1063 }
1064 }
1065 UiNodeOp::Deinit => {
1066 child.deinit();
1067 let s = WIDGET.with_state(&deinit);
1068 if s != state.get() {
1069 state.set(s);
1070 }
1071 }
1072 UiNodeOp::Update { updates } => {
1073 child.update(updates);
1074 let s = WIDGET.with_state(&predicate);
1075 if s != state.get() {
1076 state.set(s);
1077 }
1078 }
1079 _ => {}
1080 })
1081}
1082
1083pub fn widget_state_get_state<T: VarValue>(
1088 child: impl IntoUiNode,
1089 get_new: impl Fn(StateMapRef<WIDGET>, &T) -> Option<T> + Send + 'static,
1090 get_deinit: impl Fn(StateMapRef<WIDGET>, &T) -> Option<T> + Send + 'static,
1091 state: impl IntoVar<T>,
1092) -> UiNode {
1093 let state = state.into_var();
1094 match_node(child, move |child, op| match op {
1095 UiNodeOp::Init => {
1096 validate_getter_var(&state);
1097 child.init();
1098 let new = state.with(|s| WIDGET.with_state(|w| get_new(w, s)));
1099 if let Some(new) = new {
1100 state.set(new);
1101 }
1102 }
1103 UiNodeOp::Deinit => {
1104 child.deinit();
1105
1106 let new = state.with(|s| WIDGET.with_state(|w| get_deinit(w, s)));
1107 if let Some(new) = new {
1108 state.set(new);
1109 }
1110 }
1111 UiNodeOp::Update { updates } => {
1112 child.update(updates);
1113 let new = state.with(|s| WIDGET.with_state(|w| get_new(w, s)));
1114 if let Some(new) = new {
1115 state.set(new);
1116 }
1117 }
1118 _ => {}
1119 })
1120}
1121
1122pub fn fill_node(content: impl IntoUiNode) -> UiNode {
1128 let mut clip_bounds = PxSize::zero();
1129 let mut clip_corners = PxCornerRadius::zero();
1130
1131 let mut offset = PxVector::zero();
1132 let offset_key = FrameValueKey::new_unique();
1133 let mut define_frame = false;
1134
1135 match_node(content, move |child, op| match op {
1136 UiNodeOp::Init => {
1137 WIDGET.sub_var_layout(&BORDER_ALIGN_VAR);
1138 define_frame = false;
1139 offset = PxVector::zero();
1140 }
1141 UiNodeOp::Measure { desired_size, .. } => {
1142 let offsets = BORDER.inner_offsets();
1143 let align = BORDER_ALIGN_VAR.get();
1144
1145 let our_offsets = offsets * align;
1146 let size_offset = offsets - our_offsets;
1147
1148 let size_increase = PxSize::new(size_offset.horizontal(), size_offset.vertical());
1149
1150 *desired_size = LAYOUT.constraints().fill_size() + size_increase;
1151 }
1152 UiNodeOp::Layout { wl, final_size } => {
1153 let (bounds, corners) = BORDER.fill_bounds();
1158
1159 let mut new_offset = bounds.origin.to_vector();
1160
1161 if clip_bounds != bounds.size || clip_corners != corners {
1162 clip_bounds = bounds.size;
1163 clip_corners = corners;
1164 WIDGET.render();
1165 }
1166
1167 let (_, branch_offset) = LAYOUT.with_constraints(PxConstraints2d::new_exact_size(bounds.size), || {
1168 wl.with_branch_child(|wl| child.layout(wl))
1169 });
1170 new_offset += branch_offset;
1171
1172 if offset != new_offset {
1173 offset = new_offset;
1174
1175 if define_frame {
1176 WIDGET.render_update();
1177 } else {
1178 define_frame = true;
1179 WIDGET.render();
1180 }
1181 }
1182
1183 *final_size = bounds.size;
1184 }
1185 UiNodeOp::Render { frame } => {
1186 let mut render = |frame: &mut FrameBuilder| {
1187 let bounds = PxRect::from_size(clip_bounds);
1188 frame.push_clips(
1189 |c| {
1190 if clip_corners != PxCornerRadius::zero() {
1191 c.push_clip_rounded_rect(bounds, clip_corners, false, false);
1192 } else {
1193 c.push_clip_rect(bounds, false, false);
1194 }
1195
1196 if let Some(inline) = WIDGET.bounds().inline() {
1197 for r in inline.negative_space().iter() {
1198 c.push_clip_rect(*r, true, false);
1199 }
1200 }
1201 },
1202 |f| child.render(f),
1203 );
1204 };
1205
1206 if define_frame {
1207 frame.push_reference_frame(offset_key.into(), offset_key.bind(offset.into(), false), true, false, |frame| {
1208 render(frame);
1209 });
1210 } else {
1211 render(frame);
1212 }
1213 }
1214 UiNodeOp::RenderUpdate { update } => {
1215 if define_frame {
1216 update.with_transform(offset_key.update(offset.into(), false), false, |update| {
1217 child.render_update(update);
1218 });
1219 } else {
1220 child.render_update(update);
1221 }
1222 }
1223 _ => {}
1224 })
1225}
1226
1227pub fn border_node(child: impl IntoUiNode, border_offsets: impl IntoVar<SideOffsets>, border_visual: impl IntoUiNode) -> UiNode {
1232 let offsets = border_offsets.into_var();
1233 let mut render_offsets = PxSideOffsets::zero();
1234 let mut border_rect = PxRect::zero();
1235
1236 match_node(ui_vec![child, border_visual], move |children, op| match op {
1237 UiNodeOp::Init => {
1238 WIDGET.sub_var_layout(&offsets).sub_var_render(&BORDER_OVER_VAR);
1239 }
1240 UiNodeOp::Measure { wm, desired_size } => {
1241 let offsets = offsets.layout();
1242 *desired_size = BORDER.measure_border(offsets, || {
1243 LAYOUT.with_sub_size(PxSize::new(offsets.horizontal(), offsets.vertical()), || {
1244 children.node().with_child(0, |n| wm.measure_block(n))
1245 })
1246 });
1247 children.delegated();
1248 }
1249 UiNodeOp::Layout { wl, final_size } => {
1250 let offsets = offsets.layout();
1258 if render_offsets != offsets {
1259 render_offsets = offsets;
1260 WIDGET.render();
1261 }
1262
1263 let parent_offsets = BORDER.inner_offsets();
1264 let origin = PxPoint::new(parent_offsets.left, parent_offsets.top);
1265 if border_rect.origin != origin {
1266 border_rect.origin = origin;
1267 WIDGET.render();
1268 }
1269
1270 BORDER.layout_border(offsets, || {
1272 wl.translate(PxVector::new(offsets.left, offsets.top));
1273
1274 let taken_size = PxSize::new(offsets.horizontal(), offsets.vertical());
1275 border_rect.size = LAYOUT.with_sub_size(taken_size, || children.node().with_child(0, |n| n.layout(wl)));
1276
1277 LAYOUT.with_constraints(PxConstraints2d::new_exact_size(border_rect.size), || {
1279 BORDER.with_border_layout(border_rect, offsets, || {
1280 children.node().with_child(1, |n| n.layout(wl));
1281 });
1282 });
1283 });
1284 children.delegated();
1285
1286 *final_size = border_rect.size;
1287 }
1288 UiNodeOp::Render { frame } => {
1289 if BORDER_OVER_VAR.get() {
1290 children.node().with_child(0, |c| c.render(frame));
1291 BORDER.with_border_layout(border_rect, render_offsets, || {
1292 children.node().with_child(1, |c| c.render(frame));
1293 });
1294 } else {
1295 BORDER.with_border_layout(border_rect, render_offsets, || {
1296 children.node().with_child(1, |c| c.render(frame));
1297 });
1298 children.node().with_child(0, |c| c.render(frame));
1299 }
1300 children.delegated();
1301 }
1302 UiNodeOp::RenderUpdate { update } => {
1303 children.node().with_child(0, |c| c.render_update(update));
1304 BORDER.with_border_layout(border_rect, render_offsets, || {
1305 children.node().with_child(1, |c| c.render_update(update));
1306 });
1307 children.delegated();
1308 }
1309 _ => {}
1310 })
1311}
1312
1313pub fn with_context_local<T: Any + Send + Sync + 'static>(
1319 child: impl IntoUiNode,
1320 context: &'static ContextLocal<T>,
1321 value: impl Into<T>,
1322) -> UiNode {
1323 let mut value = Some(Arc::new(value.into()));
1324
1325 match_node(child, move |child, op| {
1326 context.with_context(&mut value, || child.op(op));
1327 })
1328}
1329
1330pub fn with_context_local_init<T: Any + Send + Sync + 'static>(
1339 child: impl IntoUiNode,
1340 context: &'static ContextLocal<T>,
1341 init_value: impl FnMut() -> T + Send + 'static,
1342) -> UiNode {
1343 with_context_local_init_impl(child.into_node(), context, init_value)
1344}
1345fn with_context_local_init_impl<T: Any + Send + Sync + 'static>(
1346 child: UiNode,
1347 context: &'static ContextLocal<T>,
1348 mut init_value: impl FnMut() -> T + Send + 'static,
1349) -> UiNode {
1350 let mut value = None;
1351
1352 match_node(child, move |child, op| {
1353 let mut is_deinit = false;
1354 match &op {
1355 UiNodeOp::Init => {
1356 value = Some(Arc::new(init_value()));
1357 }
1358 UiNodeOp::Deinit => {
1359 is_deinit = true;
1360 }
1361 _ => {}
1362 }
1363
1364 context.with_context(&mut value, || child.op(op));
1365
1366 if is_deinit {
1367 value = None;
1368 }
1369 })
1370}
1371
1372pub fn with_context_blend(mut ctx: LocalContext, over: bool, child: impl IntoUiNode) -> UiNode {
1401 match_widget(child, move |c, op| {
1402 if let UiNodeOp::Init = op {
1403 let init_app = LocalContext::current_app();
1404 ctx.with_context_blend(over, || {
1405 let ctx_app = LocalContext::current_app();
1406 assert_eq!(init_app, ctx_app);
1407 c.op(op)
1408 });
1409 } else {
1410 ctx.with_context_blend(over, || c.op(op));
1411 }
1412 })
1413}
1414
1415pub fn with_widget_state<U, I, T>(child: U, id: impl Into<StateId<T>>, default: I, value: impl IntoVar<T>) -> UiNode
1457where
1458 U: IntoUiNode,
1459 I: Fn() -> T + Send + 'static,
1460 T: StateValue + VarValue,
1461{
1462 with_widget_state_impl(child.into_node(), id.into(), default, value.into_var())
1463}
1464fn with_widget_state_impl<I, T>(child: UiNode, id: impl Into<StateId<T>>, default: I, value: impl IntoVar<T>) -> UiNode
1465where
1466 I: Fn() -> T + Send + 'static,
1467 T: StateValue + VarValue,
1468{
1469 let id = id.into();
1470 let value = value.into_var();
1471
1472 match_node(child, move |child, op| match op {
1473 UiNodeOp::Init => {
1474 child.init();
1475 WIDGET.sub_var(&value);
1476 WIDGET.set_state(id, value.get());
1477 }
1478 UiNodeOp::Deinit => {
1479 child.deinit();
1480 WIDGET.set_state(id, default());
1481 }
1482 UiNodeOp::Update { updates } => {
1483 child.update(updates);
1484 if let Some(v) = value.get_new() {
1485 WIDGET.set_state(id, v);
1486 }
1487 }
1488 _ => {}
1489 })
1490}
1491
1492pub 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
1500where
1501 U: IntoUiNode,
1502 S: StateValue,
1503 V: VarValue,
1504 I: Fn() -> S + Send + 'static,
1505 M: FnMut(&mut S, &V) + Send + 'static,
1506{
1507 with_widget_state_modify_impl(child.into_node(), id.into(), value.into_var(), default, modify)
1508}
1509fn with_widget_state_modify_impl<S, V, I, M>(
1510 child: UiNode,
1511 id: impl Into<StateId<S>>,
1512 value: impl IntoVar<V>,
1513 default: I,
1514 mut modify: M,
1515) -> UiNode
1516where
1517 S: StateValue,
1518 V: VarValue,
1519 I: Fn() -> S + Send + 'static,
1520 M: FnMut(&mut S, &V) + Send + 'static,
1521{
1522 let id = id.into();
1523 let value = value.into_var();
1524
1525 match_node(child, move |child, op| match op {
1526 UiNodeOp::Init => {
1527 child.init();
1528
1529 WIDGET.sub_var(&value);
1530
1531 value.with(|v| {
1532 WIDGET.with_state_mut(|mut s| {
1533 modify(s.entry(id).or_insert_with(&default), v);
1534 })
1535 })
1536 }
1537 UiNodeOp::Deinit => {
1538 child.deinit();
1539
1540 WIDGET.set_state(id, default());
1541 }
1542 UiNodeOp::Update { updates } => {
1543 child.update(updates);
1544 value.with_new(|v| {
1545 WIDGET.with_state_mut(|mut s| {
1546 modify(s.req_mut(id), v);
1547 })
1548 });
1549 }
1550 _ => {}
1551 })
1552}
1553
1554pub fn interactive_node(child: impl IntoUiNode, interactive: impl IntoVar<bool>) -> UiNode {
1566 let interactive = interactive.into_var();
1567
1568 match_node(child, move |child, op| match op {
1569 UiNodeOp::Init => {
1570 WIDGET.sub_var_info(&interactive);
1571 }
1572 UiNodeOp::Info { info } => {
1573 if interactive.get() {
1574 child.info(info);
1575 } else if let Some(mut wgt) = child.node().as_widget() {
1576 let id = wgt.id();
1577 info.push_interactivity_filter(move |args| {
1579 if args.info.id() == id {
1580 Interactivity::BLOCKED
1581 } else {
1582 Interactivity::ENABLED
1583 }
1584 });
1585 child.info(info);
1586 } else {
1587 let block_range = info.with_children_range(|info| child.info(info));
1588 if !block_range.is_empty() {
1589 let id = WIDGET.id();
1592 info.push_interactivity_filter(move |args| {
1593 if let Some(parent) = args.info.parent()
1594 && parent.id() == id
1595 {
1596 for (i, item) in parent.children().enumerate() {
1598 if item == args.info {
1599 return if !block_range.contains(&i) {
1600 Interactivity::ENABLED
1601 } else {
1602 Interactivity::BLOCKED
1603 };
1604 } else if i >= block_range.end {
1605 break;
1606 }
1607 }
1608 }
1609 Interactivity::ENABLED
1610 });
1611 }
1612 }
1613 }
1614 _ => {}
1615 })
1616}
1617
1618pub fn with_index_node(
1622 child: impl IntoUiNode,
1623 panel_list_id: impl Into<StateId<PanelListRange>>,
1624 mut update: impl FnMut(Option<usize>) + Send + 'static,
1625) -> UiNode {
1626 let panel_list_id = panel_list_id.into();
1627 let mut version = None;
1628 match_node(child, move |_, op| match op {
1629 UiNodeOp::Deinit => {
1630 update(None);
1631 version = None;
1632 }
1633 UiNodeOp::Update { .. } => {
1634 let info = WIDGET.info();
1636 if let Some(parent) = info.parent()
1637 && let Some(mut c) = PanelListRange::update(&parent, panel_list_id, &mut version)
1638 {
1639 let id = info.id();
1640 let p = c.position(|w| w.id() == id);
1641 update(p);
1642 }
1643 }
1644 _ => {}
1645 })
1646}
1647
1648pub fn with_rev_index_node(
1652 child: impl IntoUiNode,
1653 panel_list_id: impl Into<StateId<PanelListRange>>,
1654 mut update: impl FnMut(Option<usize>) + Send + 'static,
1655) -> UiNode {
1656 let panel_list_id = panel_list_id.into();
1657 let mut version = None;
1658 match_node(child, move |_, op| match op {
1659 UiNodeOp::Deinit => {
1660 update(None);
1661 version = None;
1662 }
1663 UiNodeOp::Update { .. } => {
1664 let info = WIDGET.info();
1665 if let Some(parent) = info.parent()
1666 && let Some(c) = PanelListRange::update(&parent, panel_list_id, &mut version)
1667 {
1668 let id = info.id();
1669 let p = c.rev().position(|w| w.id() == id);
1670 update(p);
1671 }
1672 }
1673 _ => {}
1674 })
1675}
1676
1677pub fn with_index_len_node(
1684 child: impl IntoUiNode,
1685 panel_list_id: impl Into<StateId<PanelListRange>>,
1686 mut update: impl FnMut(Option<(usize, usize)>) + Send + 'static,
1687) -> UiNode {
1688 let panel_list_id = panel_list_id.into();
1689 let mut version = None;
1690 match_node(child, move |_, op| match op {
1691 UiNodeOp::Deinit => {
1692 update(None);
1693 version = None;
1694 }
1695 UiNodeOp::Update { .. } => {
1696 let info = WIDGET.info();
1697 if let Some(parent) = info.parent()
1698 && let Some(mut iter) = PanelListRange::update(&parent, panel_list_id, &mut version)
1699 {
1700 let id = info.id();
1701 let mut p = 0;
1702 let mut count = 0;
1703 for c in &mut iter {
1704 if c.id() == id {
1705 p = count;
1706 count += 1 + iter.count();
1707 break;
1708 } else {
1709 count += 1;
1710 }
1711 }
1712 update(Some((p, count)));
1713 }
1714 }
1715 _ => {}
1716 })
1717}
1718
1719pub fn presenter<D: VarValue>(data: impl IntoVar<D>, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1729 let data = data.into_var();
1730 let wgt_fn = wgt_fn.into_var();
1731
1732 match_widget(UiNode::nil(), move |c, op| match op {
1733 UiNodeOp::Init => {
1734 WIDGET.sub_var(&data).sub_var(&wgt_fn);
1735 *c.node() = wgt_fn.get()(data.get());
1736 }
1737 UiNodeOp::Deinit => {
1738 c.deinit();
1739 *c.node() = UiNode::nil();
1740 }
1741 UiNodeOp::Update { .. } => {
1742 if data.is_new() || wgt_fn.is_new() {
1743 c.node().deinit();
1744 *c.node() = wgt_fn.get()(data.get());
1745 c.node().init();
1746 c.delegated();
1747 WIDGET.update_info().layout().render();
1748 }
1749 }
1750 _ => {}
1751 })
1752}
1753
1754pub fn presenter_opt<D: VarValue>(data: impl IntoVar<Option<D>>, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1760 let data = data.into_var();
1761 let wgt_fn = wgt_fn.into_var();
1762
1763 match_widget(UiNode::nil(), move |c, op| match op {
1764 UiNodeOp::Init => {
1765 WIDGET.sub_var(&data).sub_var(&wgt_fn);
1766 if let Some(data) = data.get() {
1767 *c.node() = wgt_fn.get()(data);
1768 }
1769 }
1770 UiNodeOp::Deinit => {
1771 c.deinit();
1772 *c.node() = UiNode::nil();
1773 }
1774 UiNodeOp::Update { .. } => {
1775 if data.is_new() || wgt_fn.is_new() {
1776 if let Some(data) = data.get() {
1777 c.node().deinit();
1778 *c.node() = wgt_fn.get()(data);
1779 c.node().init();
1780 c.delegated();
1781 WIDGET.update_info().layout().render();
1782 } else if !c.node().is_nil() {
1783 c.node().deinit();
1784 *c.node() = UiNode::nil();
1785 c.delegated();
1786 WIDGET.update_info().layout().render();
1787 }
1788 }
1789 }
1790 _ => {}
1791 })
1792}
1793
1794pub fn list_presenter<D: VarValue>(list: impl IntoVar<ObservableVec<D>>, item_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1800 ListPresenter {
1801 list: list.into_var(),
1802 item_fn: item_fn.into_var(),
1803 view: ui_vec![],
1804 _e: std::marker::PhantomData,
1805 }
1806 .into_node()
1807}
1808
1809pub fn list_presenter_from_iter<D, L>(list: impl IntoVar<L>, item_fn: impl IntoVar<WidgetFn<D>>) -> UiNode
1815where
1816 D: VarValue,
1817 L: IntoIterator<Item = D> + VarValue,
1818{
1819 ListPresenterFromIter {
1820 list: list.into_var(),
1821 item_fn: item_fn.into_var(),
1822 view: ui_vec![],
1823 _e: std::marker::PhantomData,
1824 }
1825 .into_node()
1826}
1827
1828struct ListPresenter<D>
1829where
1830 D: VarValue,
1831{
1832 list: Var<ObservableVec<D>>,
1833 item_fn: Var<WidgetFn<D>>,
1834 view: UiVec,
1835 _e: std::marker::PhantomData<D>,
1836}
1837
1838impl<D> UiNodeImpl for ListPresenter<D>
1839where
1840 D: VarValue,
1841{
1842 fn children_len(&self) -> usize {
1843 self.view.len()
1844 }
1845
1846 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
1847 self.view.with_child(index, visitor)
1848 }
1849
1850 fn is_list(&self) -> bool {
1851 true
1852 }
1853
1854 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
1855 self.view.for_each_child(visitor);
1856 }
1857
1858 fn try_for_each_child(
1859 &mut self,
1860 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<BoxAnyVarValue>,
1861 ) -> std::ops::ControlFlow<BoxAnyVarValue> {
1862 self.view.try_for_each_child(visitor)
1863 }
1864
1865 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
1866 self.view.par_each_child(visitor);
1867 }
1868
1869 fn par_fold_reduce(
1870 &mut self,
1871 identity: BoxAnyVarValue,
1872 fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
1873 reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
1874 ) -> BoxAnyVarValue {
1875 self.view.par_fold_reduce(identity, fold, reduce)
1876 }
1877
1878 fn init(&mut self) {
1879 debug_assert!(self.view.is_empty());
1880 self.view.clear();
1881
1882 WIDGET.sub_var(&self.list).sub_var(&self.item_fn);
1883
1884 let e_fn = self.item_fn.get();
1885 self.list.with(|l| {
1886 for el in l.iter() {
1887 let child = e_fn(el.clone());
1888 self.view.push(child);
1889 }
1890 });
1891
1892 self.view.init();
1893 }
1894
1895 fn deinit(&mut self) {
1896 self.view.deinit();
1897 self.view.clear();
1898 }
1899
1900 fn update(&mut self, updates: &WidgetUpdates) {
1901 self.update_list(updates, &mut ());
1902 }
1903
1904 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
1905 let mut need_reset = self.item_fn.is_new();
1906
1907 let is_new = self
1908 .list
1909 .with_new(|l| {
1910 need_reset |= l.changes().is_empty() || l.changes() == [VecChange::Clear];
1911
1912 if need_reset {
1913 return;
1914 }
1915
1916 self.view.update_list(updates, observer);
1918
1919 let e_fn = self.item_fn.get();
1920
1921 for change in l.changes() {
1922 match change {
1923 VecChange::Insert { index, count } => {
1924 for i in *index..(*index + count) {
1925 let mut el = e_fn(l[i].clone());
1926 el.init();
1927 self.view.insert(i, el);
1928 observer.inserted(i);
1929 }
1930 }
1931 VecChange::Remove { index, count } => {
1932 let mut count = *count;
1933 let index = *index;
1934 while count > 0 {
1935 count -= 1;
1936
1937 let mut el = self.view.remove(index);
1938 el.deinit();
1939 observer.removed(index);
1940 }
1941 }
1942 VecChange::Move { from_index, to_index } => {
1943 let el = self.view.remove(*from_index);
1944 self.view.insert(*to_index, el);
1945 observer.moved(*from_index, *to_index);
1946 }
1947 VecChange::Clear => unreachable!(),
1948 }
1949 }
1950 })
1951 .is_some();
1952
1953 if !need_reset && !is_new && self.list.with(|l| l.len() != self.view.len()) {
1954 need_reset = true;
1955 }
1956
1957 if need_reset {
1958 self.view.deinit();
1959 self.view.clear();
1960
1961 let e_fn = self.item_fn.get();
1962 self.list.with(|l| {
1963 for el in l.iter() {
1964 let child = e_fn(el.clone());
1965 self.view.push(child);
1966 }
1967 });
1968
1969 self.view.init();
1970 } else if !is_new {
1971 self.view.update_list(updates, observer);
1972 }
1973 }
1974
1975 fn info(&mut self, info: &mut zng_app::widget::info::WidgetInfoBuilder) {
1976 self.view.info(info);
1977 }
1978
1979 fn measure(&mut self, wm: &mut zng_app::widget::info::WidgetMeasure) -> PxSize {
1980 self.view.measure(wm)
1981 }
1982
1983 fn measure_list(
1984 &mut self,
1985 wm: &mut zng_app::widget::info::WidgetMeasure,
1986 measure: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetMeasure) -> PxSize + Sync),
1987 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
1988 ) -> PxSize {
1989 self.view.measure_list(wm, measure, fold_size)
1990 }
1991
1992 fn layout(&mut self, wl: &mut zng_app::widget::info::WidgetLayout) -> PxSize {
1993 self.view.layout(wl)
1994 }
1995
1996 fn layout_list(
1997 &mut self,
1998 wl: &mut zng_app::widget::info::WidgetLayout,
1999 layout: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetLayout) -> PxSize + Sync),
2000 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2001 ) -> PxSize {
2002 self.view.layout_list(wl, layout, fold_size)
2003 }
2004
2005 fn render(&mut self, frame: &mut FrameBuilder) {
2006 self.view.render(frame);
2007 }
2008
2009 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
2010 self.view.render_list(frame, render);
2011 }
2012
2013 fn render_update(&mut self, update: &mut zng_app::render::FrameUpdate) {
2014 self.view.render_update(update);
2015 }
2016
2017 fn render_update_list(
2018 &mut self,
2019 update: &mut zng_app::render::FrameUpdate,
2020 render_update: &(dyn Fn(usize, &mut UiNode, &mut zng_app::render::FrameUpdate) + Sync),
2021 ) {
2022 self.view.render_update_list(update, render_update);
2023 }
2024
2025 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2026 None
2027 }
2028}
2029
2030struct ListPresenterFromIter<D, L>
2031where
2032 D: VarValue,
2033 L: IntoIterator<Item = D> + VarValue,
2034{
2035 list: Var<L>,
2036 item_fn: Var<WidgetFn<D>>,
2037 view: UiVec,
2038 _e: std::marker::PhantomData<(D, L)>,
2039}
2040
2041impl<D, L> UiNodeImpl for ListPresenterFromIter<D, L>
2042where
2043 D: VarValue,
2044 L: IntoIterator<Item = D> + VarValue,
2045{
2046 fn children_len(&self) -> usize {
2047 self.view.len()
2048 }
2049
2050 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
2051 self.view.with_child(index, visitor)
2052 }
2053
2054 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
2055 self.view.for_each_child(visitor)
2056 }
2057
2058 fn try_for_each_child(
2059 &mut self,
2060 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<BoxAnyVarValue>,
2061 ) -> std::ops::ControlFlow<BoxAnyVarValue> {
2062 self.view.try_for_each_child(visitor)
2063 }
2064
2065 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
2066 self.view.par_each_child(visitor);
2067 }
2068
2069 fn par_fold_reduce(
2070 &mut self,
2071 identity: BoxAnyVarValue,
2072 fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
2073 reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
2074 ) -> BoxAnyVarValue {
2075 self.view.par_fold_reduce(identity, fold, reduce)
2076 }
2077
2078 fn is_list(&self) -> bool {
2079 true
2080 }
2081
2082 fn init(&mut self) {
2083 debug_assert!(self.view.is_empty());
2084 self.view.clear();
2085
2086 WIDGET.sub_var(&self.list).sub_var(&self.item_fn);
2087
2088 let e_fn = self.item_fn.get();
2089
2090 self.view.extend(self.list.get().into_iter().map(&*e_fn));
2091 self.view.init();
2092 }
2093
2094 fn deinit(&mut self) {
2095 self.view.deinit();
2096 self.view.clear();
2097 }
2098
2099 fn update(&mut self, updates: &WidgetUpdates) {
2100 self.update_list(updates, &mut ())
2101 }
2102 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
2103 if self.list.is_new() || self.item_fn.is_new() {
2104 self.view.deinit();
2105 self.view.clear();
2106 let e_fn = self.item_fn.get();
2107 self.view.extend(self.list.get().into_iter().map(&*e_fn));
2108 self.view.init();
2109 observer.reset();
2110 } else {
2111 self.view.update_list(updates, observer);
2112 }
2113 }
2114
2115 fn info(&mut self, info: &mut zng_app::widget::info::WidgetInfoBuilder) {
2116 self.view.info(info)
2117 }
2118
2119 fn measure(&mut self, wm: &mut zng_app::widget::info::WidgetMeasure) -> PxSize {
2120 self.view.measure(wm)
2121 }
2122
2123 fn measure_list(
2124 &mut self,
2125 wm: &mut zng_app::widget::info::WidgetMeasure,
2126 measure: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetMeasure) -> PxSize + Sync),
2127 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2128 ) -> PxSize {
2129 self.view.measure_list(wm, measure, fold_size)
2130 }
2131
2132 fn layout(&mut self, wl: &mut zng_app::widget::info::WidgetLayout) -> PxSize {
2133 self.view.layout(wl)
2134 }
2135
2136 fn layout_list(
2137 &mut self,
2138 wl: &mut zng_app::widget::info::WidgetLayout,
2139 layout: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetLayout) -> PxSize + Sync),
2140 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2141 ) -> PxSize {
2142 self.view.layout_list(wl, layout, fold_size)
2143 }
2144
2145 fn render(&mut self, frame: &mut FrameBuilder) {
2146 self.view.render(frame);
2147 }
2148
2149 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
2150 self.view.render_list(frame, render);
2151 }
2152
2153 fn render_update(&mut self, update: &mut zng_app::render::FrameUpdate) {
2154 self.view.render_update(update);
2155 }
2156
2157 fn render_update_list(
2158 &mut self,
2159 update: &mut zng_app::render::FrameUpdate,
2160 render_update: &(dyn Fn(usize, &mut UiNode, &mut zng_app::render::FrameUpdate) + Sync),
2161 ) {
2162 self.view.render_update_list(update, render_update);
2163 }
2164
2165 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2166 None
2167 }
2168}
2169
2170pub trait VarPresent<D: VarValue> {
2172 fn present(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2174}
2175impl<D: VarValue> VarPresent<D> for Var<D> {
2176 fn present(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2177 presenter(self.clone(), wgt_fn)
2178 }
2179}
2180
2181pub trait VarPresentOpt<D: VarValue> {
2183 fn present_opt(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2185}
2186impl<D: VarValue> VarPresentOpt<D> for Var<Option<D>> {
2187 fn present_opt(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2188 presenter_opt(self.clone(), wgt_fn)
2189 }
2190}
2191
2192pub trait VarPresentList<D: VarValue> {
2194 fn present_list(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2196}
2197impl<D: VarValue> VarPresentList<D> for Var<ObservableVec<D>> {
2198 fn present_list(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2199 list_presenter(self.clone(), wgt_fn)
2200 }
2201}
2202
2203pub trait VarPresentListFromIter<D: VarValue, L: IntoIterator<Item = D> + VarValue> {
2205 fn present_list_from_iter(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2207}
2208impl<D: VarValue, L: IntoIterator<Item = D> + VarValue> VarPresentListFromIter<D, L> for Var<L> {
2209 fn present_list_from_iter(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2210 list_presenter_from_iter(self.clone(), wgt_fn)
2211 }
2212}
2213
2214pub trait VarPresentData<D: VarValue> {
2216 fn present_data(&self, data: impl IntoVar<D>) -> UiNode;
2218}
2219impl<D: VarValue> VarPresentData<D> for Var<WidgetFn<D>> {
2220 fn present_data(&self, data: impl IntoVar<D>) -> UiNode {
2221 presenter(data, self.clone())
2222 }
2223}