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 $(#[$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 #[$crate::node::__macro_util::property(CONTEXT, default([<$can_ident:upper _VAR>]))]
848 $vis fn $can_ident(
849 child: impl $crate::node::__macro_util::IntoUiNode,
850 enabled: impl $crate::node::__macro_util::IntoVar<bool>,
851 ) -> $crate::node::__macro_util::UiNode {
852 $crate::node::with_context_var(child, self::[<$can_ident:upper _VAR>], enabled)
853 }
854
855 $crate::event_property! {
856 $(#[$meta])+
857 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
862 #[doc = concat!("[`", stringify!($can_ident), "`](fn@", stringify!($can_ident), ")")]
867 $vis fn $on_ident<$on_pre_ident>($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
869 const PRE: bool;
870 let child = $crate::node::EventNodeBuilder::new(*$COMMAND)
871 .filter(|| {
872 let enabled = self::[<$can_ident:upper _VAR>].current_context();
873 move |_| enabled.get()
874 })
875 .build::<PRE>($child, $handler);
876 $crate::node::command_contextual_enabled(child, $COMMAND, [<$can_ident:upper _VAR>])
877 }
878 }
879 }
880 };
881 (
882 $(#[$meta:meta])+
883 $vis:vis fn $on_ident:ident< $on_pre_ident:ident> (
884 $child:ident: impl $IntoUiNode:path,
885 $handler:ident: $Handler:ty
886 ) -> $UiNode:path {
887 $COMMAND:path
888 }
889 ) => {
890 $crate::event_property! {
891 $(#[$meta])+
892 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
897 $vis fn $on_ident<$on_pre_ident>($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
902 const PRE: bool;
903 let child = $crate::node::EventNodeBuilder::new(*$COMMAND).build::<PRE>($child, $handler);
904 $crate::node::command_always_enabled(child, $COMMAND)
905 }
906 }
907 };
908 (
909 $(#[$meta:meta])+
910 $vis:vis fn $on_ident:ident (
911 $child:ident: impl $IntoUiNode:path,
912 $handler:ident: $Handler:ty
913 ) -> $UiNode:path {
914 $COMMAND:path
915 }
916 ) => {
917 $crate::event_property! {
918 $(#[$meta])+
919 #[doc = concat!("[`", stringify!($COMMAND), "`]")]
924 $vis fn $on_ident($child: impl $IntoUiNode, $handler: $Handler) -> $UiNode {
929 let child = $crate::node::EventNodeBuilder::new(*$COMMAND).build::<false>($child, $handler);
930 $crate::node::command_always_enabled(child, $COMMAND)
931 }
932 }
933 };
934}
935
936fn validate_cmd(cmd: Command) {
937 if !matches!(cmd.scope(), CommandScope::App) {
938 tracing::error!("command for command property cannot be scoped, {cmd:?} scope will be ignored");
939 }
940}
941
942#[doc(hidden)]
943pub fn command_always_enabled(child: UiNode, cmd: Command) -> UiNode {
944 let mut _wgt_handle = CommandHandle::dummy();
945 let mut _win_handle = CommandHandle::dummy();
946 match_node(child, move |_, op| match op {
947 UiNodeOp::Init => {
948 validate_cmd(cmd);
949 _wgt_handle = cmd.scoped(WIDGET.id()).subscribe(true);
950 if WIDGET.parent_id().is_none() {
951 _win_handle = cmd.scoped(WINDOW.id()).subscribe(true);
952 }
953 }
954 UiNodeOp::Deinit => {
955 _wgt_handle = CommandHandle::dummy();
956 _win_handle = CommandHandle::dummy();
957 }
958 _ => {}
959 })
960}
961
962#[doc(hidden)]
963pub fn command_contextual_enabled(child: UiNode, cmd: Command, ctx: ContextVar<bool>) -> UiNode {
964 let mut _handle = VarHandle::dummy();
965 let mut _wgt_handle = CommandHandle::dummy();
966 let mut _win_handle = CommandHandle::dummy();
967 match_node(child, move |_, op| match op {
968 UiNodeOp::Init => {
969 let ctx = ctx.current_context();
970 let handle = cmd.scoped(WIDGET.id()).subscribe(ctx.get());
971 let win_handle = if WIDGET.parent_id().is_none() {
972 cmd.scoped(WINDOW.id()).subscribe(ctx.get())
973 } else {
974 CommandHandle::dummy()
975 };
976 if !ctx.capabilities().is_const() {
977 let handle = handle.enabled().clone();
978 let win_handle = win_handle.enabled().clone();
979 _handle = ctx.hook(move |a| {
980 handle.set(*a.value());
981 win_handle.set(*a.value());
982 true
983 });
984 }
985 _wgt_handle = handle;
986 _win_handle = win_handle;
987 }
988 UiNodeOp::Deinit => {
989 _handle = VarHandle::dummy();
990 _wgt_handle = CommandHandle::dummy();
991 _win_handle = CommandHandle::dummy();
992 }
993 _ => {}
994 })
995}
996
997pub fn validate_getter_var<T: VarValue>(_var: &Var<T>) {
999 #[cfg(debug_assertions)]
1000 if _var.capabilities().is_always_read_only() {
1001 tracing::error!(
1002 "`is_`, `has_` or `get_` property inited with read-only var in `{}`",
1003 WIDGET.trace_id()
1004 );
1005 }
1006}
1007
1008pub fn bind_state<T: VarValue>(child: impl IntoUiNode, source: impl IntoVar<T>, state: impl IntoVar<T>) -> UiNode {
1013 let source = source.into_var();
1014 bind_state_init(child, state, move |state| {
1015 state.set_from(&source);
1016 source.bind(state)
1017 })
1018}
1019
1020pub fn bind_state_init<T>(
1024 child: impl IntoUiNode,
1025 state: impl IntoVar<T>,
1026 mut bind: impl FnMut(&Var<T>) -> VarHandle + Send + 'static,
1027) -> UiNode
1028where
1029 T: VarValue,
1030{
1031 let state = state.into_var();
1032 let mut _binding = VarHandle::dummy();
1033
1034 match_node(child, move |_, op| match op {
1035 UiNodeOp::Init => {
1036 validate_getter_var(&state);
1037 _binding = bind(&state);
1038 }
1039 UiNodeOp::Deinit => {
1040 _binding = VarHandle::dummy();
1041 }
1042 _ => {}
1043 })
1044}
1045
1046pub fn bind_state_info<T>(
1050 child: impl IntoUiNode,
1051 state: impl IntoVar<T>,
1052 mut bind: impl FnMut(&Var<T>) -> VarHandle + Send + 'static,
1053) -> UiNode
1054where
1055 T: VarValue,
1056{
1057 let state = state.into_var();
1058 let mut _binding = VarHandle::dummy();
1059
1060 match_node(child, move |_, op| match op {
1061 UiNodeOp::Init => {
1062 let id = WINDOW.id();
1063 WIDGET.sub_event_when(&WIDGET_TREE_CHANGED_EVENT, move |a| !a.is_update && a.tree.window_id() == id);
1064 }
1065 UiNodeOp::Update { .. } => {
1066 WIDGET_TREE_CHANGED_EVENT.each_update(true, |a| {
1067 if !a.is_update && a.tree.window_id() == WINDOW.id() {
1068 _binding = bind(&state);
1069 }
1070 });
1071 }
1072 UiNodeOp::Deinit => {
1073 _binding = VarHandle::dummy();
1074 }
1075 _ => {}
1076 })
1077}
1078
1079pub fn widget_state_is_state(
1084 child: impl IntoUiNode,
1085 predicate: impl Fn(StateMapRef<WIDGET>) -> bool + Send + 'static,
1086 deinit: impl Fn(StateMapRef<WIDGET>) -> bool + Send + 'static,
1087 state: impl IntoVar<bool>,
1088) -> UiNode {
1089 let state = state.into_var();
1090
1091 match_node(child, move |child, op| match op {
1092 UiNodeOp::Init => {
1093 validate_getter_var(&state);
1094 child.init();
1095 let s = WIDGET.with_state(&predicate);
1096 if s != state.get() {
1097 state.set(s);
1098 }
1099 }
1100 UiNodeOp::Deinit => {
1101 child.deinit();
1102 let s = WIDGET.with_state(&deinit);
1103 if s != state.get() {
1104 state.set(s);
1105 }
1106 }
1107 UiNodeOp::Update { updates } => {
1108 child.update(updates);
1109 let s = WIDGET.with_state(&predicate);
1110 if s != state.get() {
1111 state.set(s);
1112 }
1113 }
1114 _ => {}
1115 })
1116}
1117
1118pub fn widget_state_get_state<T: VarValue>(
1123 child: impl IntoUiNode,
1124 get_new: impl Fn(StateMapRef<WIDGET>, &T) -> Option<T> + Send + 'static,
1125 get_deinit: impl Fn(StateMapRef<WIDGET>, &T) -> Option<T> + Send + 'static,
1126 state: impl IntoVar<T>,
1127) -> UiNode {
1128 let state = state.into_var();
1129 match_node(child, move |child, op| match op {
1130 UiNodeOp::Init => {
1131 validate_getter_var(&state);
1132 child.init();
1133 let new = state.with(|s| WIDGET.with_state(|w| get_new(w, s)));
1134 if let Some(new) = new {
1135 state.set(new);
1136 }
1137 }
1138 UiNodeOp::Deinit => {
1139 child.deinit();
1140
1141 let new = state.with(|s| WIDGET.with_state(|w| get_deinit(w, s)));
1142 if let Some(new) = new {
1143 state.set(new);
1144 }
1145 }
1146 UiNodeOp::Update { updates } => {
1147 child.update(updates);
1148 let new = state.with(|s| WIDGET.with_state(|w| get_new(w, s)));
1149 if let Some(new) = new {
1150 state.set(new);
1151 }
1152 }
1153 _ => {}
1154 })
1155}
1156
1157pub fn fill_node(content: impl IntoUiNode) -> UiNode {
1163 let mut clip_bounds = PxSize::zero();
1164 let mut clip_corners = PxCornerRadius::zero();
1165
1166 let mut offset = PxVector::zero();
1167 let offset_key = FrameValueKey::new_unique();
1168 let mut define_frame = false;
1169
1170 match_node(content, move |child, op| match op {
1171 UiNodeOp::Init => {
1172 WIDGET.sub_var_layout(&BORDER_ALIGN_VAR);
1173 define_frame = false;
1174 offset = PxVector::zero();
1175 }
1176 UiNodeOp::Measure { desired_size, .. } => {
1177 let offsets = BORDER.inner_offsets();
1178 let align = BORDER_ALIGN_VAR.get();
1179
1180 let our_offsets = offsets * align;
1181 let size_offset = offsets - our_offsets;
1182
1183 let size_increase = PxSize::new(size_offset.horizontal(), size_offset.vertical());
1184
1185 *desired_size = LAYOUT.constraints().fill_size() + size_increase;
1186 }
1187 UiNodeOp::Layout { wl, final_size } => {
1188 let (bounds, corners) = BORDER.fill_bounds();
1193
1194 let mut new_offset = bounds.origin.to_vector();
1195
1196 if clip_bounds != bounds.size || clip_corners != corners {
1197 clip_bounds = bounds.size;
1198 clip_corners = corners;
1199 WIDGET.render();
1200 }
1201
1202 let (_, branch_offset) = LAYOUT.with_constraints(PxConstraints2d::new_exact_size(bounds.size), || {
1203 wl.with_branch_child(|wl| child.layout(wl))
1204 });
1205 new_offset += branch_offset;
1206
1207 if offset != new_offset {
1208 offset = new_offset;
1209
1210 if define_frame {
1211 WIDGET.render_update();
1212 } else {
1213 define_frame = true;
1214 WIDGET.render();
1215 }
1216 }
1217
1218 *final_size = bounds.size;
1219 }
1220 UiNodeOp::Render { frame } => {
1221 let mut render = |frame: &mut FrameBuilder| {
1222 let bounds = PxRect::from_size(clip_bounds);
1223 frame.push_clips(
1224 |c| {
1225 if clip_corners != PxCornerRadius::zero() {
1226 c.push_clip_rounded_rect(bounds, clip_corners, false, false);
1227 } else {
1228 c.push_clip_rect(bounds, false, false);
1229 }
1230
1231 if let Some(inline) = WIDGET.bounds().inline() {
1232 for r in inline.negative_space().iter() {
1233 c.push_clip_rect(*r, true, false);
1234 }
1235 }
1236 },
1237 |f| child.render(f),
1238 );
1239 };
1240
1241 if define_frame {
1242 frame.push_reference_frame(offset_key.into(), offset_key.bind(offset.into(), false), true, false, |frame| {
1243 render(frame);
1244 });
1245 } else {
1246 render(frame);
1247 }
1248 }
1249 UiNodeOp::RenderUpdate { update } => {
1250 if define_frame {
1251 update.with_transform(offset_key.update(offset.into(), false), false, |update| {
1252 child.render_update(update);
1253 });
1254 } else {
1255 child.render_update(update);
1256 }
1257 }
1258 _ => {}
1259 })
1260}
1261
1262pub fn border_node(child: impl IntoUiNode, border_offsets: impl IntoVar<SideOffsets>, border_visual: impl IntoUiNode) -> UiNode {
1267 let offsets = border_offsets.into_var();
1268 let mut render_offsets = PxSideOffsets::zero();
1269 let mut border_rect = PxRect::zero();
1270
1271 match_node(ui_vec![child, border_visual], move |children, op| match op {
1272 UiNodeOp::Init => {
1273 WIDGET.sub_var_layout(&offsets).sub_var_render(&BORDER_OVER_VAR);
1274 }
1275 UiNodeOp::Measure { wm, desired_size } => {
1276 let offsets = offsets.layout();
1277 *desired_size = BORDER.measure_border(offsets, || {
1278 LAYOUT.with_sub_size(PxSize::new(offsets.horizontal(), offsets.vertical()), || {
1279 children.node().with_child(0, |n| wm.measure_block(n))
1280 })
1281 });
1282 children.delegated();
1283 }
1284 UiNodeOp::Layout { wl, final_size } => {
1285 let offsets = offsets.layout();
1293 if render_offsets != offsets {
1294 render_offsets = offsets;
1295 WIDGET.render();
1296 }
1297
1298 let parent_offsets = BORDER.inner_offsets();
1299 let origin = PxPoint::new(parent_offsets.left, parent_offsets.top);
1300 if border_rect.origin != origin {
1301 border_rect.origin = origin;
1302 WIDGET.render();
1303 }
1304
1305 BORDER.layout_border(offsets, || {
1307 wl.translate(PxVector::new(offsets.left, offsets.top));
1308
1309 let taken_size = PxSize::new(offsets.horizontal(), offsets.vertical());
1310 border_rect.size = LAYOUT.with_sub_size(taken_size, || children.node().with_child(0, |n| n.layout(wl)));
1311
1312 LAYOUT.with_constraints(PxConstraints2d::new_exact_size(border_rect.size), || {
1314 BORDER.with_border_layout(border_rect, offsets, || {
1315 children.node().with_child(1, |n| n.layout(wl));
1316 });
1317 });
1318 });
1319 children.delegated();
1320
1321 *final_size = border_rect.size;
1322 }
1323 UiNodeOp::Render { frame } => {
1324 if BORDER_OVER_VAR.get() {
1325 children.node().with_child(0, |c| c.render(frame));
1326 BORDER.with_border_layout(border_rect, render_offsets, || {
1327 children.node().with_child(1, |c| c.render(frame));
1328 });
1329 } else {
1330 BORDER.with_border_layout(border_rect, render_offsets, || {
1331 children.node().with_child(1, |c| c.render(frame));
1332 });
1333 children.node().with_child(0, |c| c.render(frame));
1334 }
1335 children.delegated();
1336 }
1337 UiNodeOp::RenderUpdate { update } => {
1338 children.node().with_child(0, |c| c.render_update(update));
1339 BORDER.with_border_layout(border_rect, render_offsets, || {
1340 children.node().with_child(1, |c| c.render_update(update));
1341 });
1342 children.delegated();
1343 }
1344 _ => {}
1345 })
1346}
1347
1348pub fn with_context_local<T: Any + Send + Sync + 'static>(
1354 child: impl IntoUiNode,
1355 context: &'static ContextLocal<T>,
1356 value: impl Into<T>,
1357) -> UiNode {
1358 let mut value = Some(Arc::new(value.into()));
1359
1360 match_node(child, move |child, op| {
1361 context.with_context(&mut value, || child.op(op));
1362 })
1363}
1364
1365pub fn with_context_local_init<T: Any + Send + Sync + 'static>(
1374 child: impl IntoUiNode,
1375 context: &'static ContextLocal<T>,
1376 init_value: impl FnMut() -> T + Send + 'static,
1377) -> UiNode {
1378 with_context_local_init_impl(child.into_node(), context, init_value)
1379}
1380fn with_context_local_init_impl<T: Any + Send + Sync + 'static>(
1381 child: UiNode,
1382 context: &'static ContextLocal<T>,
1383 mut init_value: impl FnMut() -> T + Send + 'static,
1384) -> UiNode {
1385 let mut value = None;
1386
1387 match_node(child, move |child, op| {
1388 let mut is_deinit = false;
1389 match &op {
1390 UiNodeOp::Init => {
1391 value = Some(Arc::new(init_value()));
1392 }
1393 UiNodeOp::Deinit => {
1394 is_deinit = true;
1395 }
1396 _ => {}
1397 }
1398
1399 context.with_context(&mut value, || child.op(op));
1400
1401 if is_deinit {
1402 value = None;
1403 }
1404 })
1405}
1406
1407pub fn with_context_blend(mut ctx: LocalContext, over: bool, child: impl IntoUiNode) -> UiNode {
1436 match_widget(child, move |c, op| {
1437 if let UiNodeOp::Init = op {
1438 let init_app = LocalContext::current_app();
1439 ctx.with_context_blend(over, || {
1440 let ctx_app = LocalContext::current_app();
1441 assert_eq!(init_app, ctx_app);
1442 c.op(op)
1443 });
1444 } else {
1445 ctx.with_context_blend(over, || c.op(op));
1446 }
1447 })
1448}
1449
1450pub fn with_widget_state<U, I, T>(child: U, id: impl Into<StateId<T>>, default: I, value: impl IntoVar<T>) -> UiNode
1492where
1493 U: IntoUiNode,
1494 I: Fn() -> T + Send + 'static,
1495 T: StateValue + VarValue,
1496{
1497 with_widget_state_impl(child.into_node(), id.into(), default, value.into_var())
1498}
1499fn with_widget_state_impl<I, T>(child: UiNode, id: impl Into<StateId<T>>, default: I, value: impl IntoVar<T>) -> UiNode
1500where
1501 I: Fn() -> T + Send + 'static,
1502 T: StateValue + VarValue,
1503{
1504 let id = id.into();
1505 let value = value.into_var();
1506
1507 match_node(child, move |child, op| match op {
1508 UiNodeOp::Init => {
1509 child.init();
1510 WIDGET.sub_var(&value);
1511 WIDGET.set_state(id, value.get());
1512 }
1513 UiNodeOp::Deinit => {
1514 child.deinit();
1515 WIDGET.set_state(id, default());
1516 }
1517 UiNodeOp::Update { updates } => {
1518 child.update(updates);
1519 if let Some(v) = value.get_new() {
1520 WIDGET.set_state(id, v);
1521 }
1522 }
1523 _ => {}
1524 })
1525}
1526
1527pub 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
1535where
1536 U: IntoUiNode,
1537 S: StateValue,
1538 V: VarValue,
1539 I: Fn() -> S + Send + 'static,
1540 M: FnMut(&mut S, &V) + Send + 'static,
1541{
1542 with_widget_state_modify_impl(child.into_node(), id.into(), value.into_var(), default, modify)
1543}
1544fn with_widget_state_modify_impl<S, V, I, M>(
1545 child: UiNode,
1546 id: impl Into<StateId<S>>,
1547 value: impl IntoVar<V>,
1548 default: I,
1549 mut modify: M,
1550) -> UiNode
1551where
1552 S: StateValue,
1553 V: VarValue,
1554 I: Fn() -> S + Send + 'static,
1555 M: FnMut(&mut S, &V) + Send + 'static,
1556{
1557 let id = id.into();
1558 let value = value.into_var();
1559
1560 match_node(child, move |child, op| match op {
1561 UiNodeOp::Init => {
1562 child.init();
1563
1564 WIDGET.sub_var(&value);
1565
1566 value.with(|v| {
1567 WIDGET.with_state_mut(|mut s| {
1568 modify(s.entry(id).or_insert_with(&default), v);
1569 })
1570 })
1571 }
1572 UiNodeOp::Deinit => {
1573 child.deinit();
1574
1575 WIDGET.set_state(id, default());
1576 }
1577 UiNodeOp::Update { updates } => {
1578 child.update(updates);
1579 value.with_new(|v| {
1580 WIDGET.with_state_mut(|mut s| {
1581 modify(s.req_mut(id), v);
1582 })
1583 });
1584 }
1585 _ => {}
1586 })
1587}
1588
1589pub fn interactive_node(child: impl IntoUiNode, interactive: impl IntoVar<bool>) -> UiNode {
1601 let interactive = interactive.into_var();
1602
1603 match_node(child, move |child, op| match op {
1604 UiNodeOp::Init => {
1605 WIDGET.sub_var_info(&interactive);
1606 }
1607 UiNodeOp::Info { info } => {
1608 if interactive.get() {
1609 child.info(info);
1610 } else if let Some(mut wgt) = child.node().as_widget() {
1611 let id = wgt.id();
1612 info.push_interactivity_filter(move |args| {
1614 if args.info.id() == id {
1615 Interactivity::BLOCKED
1616 } else {
1617 Interactivity::ENABLED
1618 }
1619 });
1620 child.info(info);
1621 } else {
1622 let block_range = info.with_children_range(|info| child.info(info));
1623 if !block_range.is_empty() {
1624 let id = WIDGET.id();
1627 info.push_interactivity_filter(move |args| {
1628 if let Some(parent) = args.info.parent()
1629 && parent.id() == id
1630 {
1631 for (i, item) in parent.children().enumerate() {
1633 if item == args.info {
1634 return if !block_range.contains(&i) {
1635 Interactivity::ENABLED
1636 } else {
1637 Interactivity::BLOCKED
1638 };
1639 } else if i >= block_range.end {
1640 break;
1641 }
1642 }
1643 }
1644 Interactivity::ENABLED
1645 });
1646 }
1647 }
1648 }
1649 _ => {}
1650 })
1651}
1652
1653pub fn with_index_node(
1657 child: impl IntoUiNode,
1658 panel_list_id: impl Into<StateId<PanelListRange>>,
1659 mut update: impl FnMut(Option<usize>) + Send + 'static,
1660) -> UiNode {
1661 let panel_list_id = panel_list_id.into();
1662 let mut version = None;
1663 match_node(child, move |_, op| match op {
1664 UiNodeOp::Deinit => {
1665 update(None);
1666 version = None;
1667 }
1668 UiNodeOp::Update { .. } => {
1669 let info = WIDGET.info();
1671 if let Some(parent) = info.parent()
1672 && let Some(mut c) = PanelListRange::update(&parent, panel_list_id, &mut version)
1673 {
1674 let id = info.id();
1675 let p = c.position(|w| w.id() == id);
1676 update(p);
1677 }
1678 }
1679 _ => {}
1680 })
1681}
1682
1683pub fn with_rev_index_node(
1687 child: impl IntoUiNode,
1688 panel_list_id: impl Into<StateId<PanelListRange>>,
1689 mut update: impl FnMut(Option<usize>) + Send + 'static,
1690) -> UiNode {
1691 let panel_list_id = panel_list_id.into();
1692 let mut version = None;
1693 match_node(child, move |_, op| match op {
1694 UiNodeOp::Deinit => {
1695 update(None);
1696 version = None;
1697 }
1698 UiNodeOp::Update { .. } => {
1699 let info = WIDGET.info();
1700 if let Some(parent) = info.parent()
1701 && let Some(c) = PanelListRange::update(&parent, panel_list_id, &mut version)
1702 {
1703 let id = info.id();
1704 let p = c.rev().position(|w| w.id() == id);
1705 update(p);
1706 }
1707 }
1708 _ => {}
1709 })
1710}
1711
1712pub fn with_index_len_node(
1719 child: impl IntoUiNode,
1720 panel_list_id: impl Into<StateId<PanelListRange>>,
1721 mut update: impl FnMut(Option<(usize, usize)>) + Send + 'static,
1722) -> UiNode {
1723 let panel_list_id = panel_list_id.into();
1724 let mut version = None;
1725 match_node(child, move |_, op| match op {
1726 UiNodeOp::Deinit => {
1727 update(None);
1728 version = None;
1729 }
1730 UiNodeOp::Update { .. } => {
1731 let info = WIDGET.info();
1732 if let Some(parent) = info.parent()
1733 && let Some(mut iter) = PanelListRange::update(&parent, panel_list_id, &mut version)
1734 {
1735 let id = info.id();
1736 let mut p = 0;
1737 let mut count = 0;
1738 for c in &mut iter {
1739 if c.id() == id {
1740 p = count;
1741 count += 1 + iter.count();
1742 break;
1743 } else {
1744 count += 1;
1745 }
1746 }
1747 update(Some((p, count)));
1748 }
1749 }
1750 _ => {}
1751 })
1752}
1753
1754pub fn presenter<D: VarValue>(data: impl IntoVar<D>, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1767 Presenter {
1768 data: data.into_var(),
1769 wgt_fn: wgt_fn.into_var(),
1770 child: UiNode::nil(),
1771 }
1772 .into_node()
1773}
1774
1775pub fn presenter_opt<D: VarValue>(data: impl IntoVar<Option<D>>, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1781 presenter(
1782 data,
1783 wgt_fn.into_var().map(|w_fn| {
1784 crate::wgt_fn!(w_fn, |d| match d {
1785 Some(d) => w_fn(d),
1786 None => UiNode::nil(),
1787 })
1788 }),
1789 )
1790}
1791
1792pub fn list_presenter<D: VarValue>(list: impl IntoVar<ObservableVec<D>>, item_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
1798 ListPresenter {
1799 list: list.into_var(),
1800 item_fn: item_fn.into_var(),
1801 view: ui_vec![],
1802 }
1803 .into_node()
1804}
1805
1806pub fn list_presenter_from_iter<D, L>(list: impl IntoVar<L>, item_fn: impl IntoVar<WidgetFn<D>>) -> UiNode
1812where
1813 D: VarValue,
1814 L: IntoIterator<Item = D> + VarValue,
1815{
1816 ListPresenterFromIter {
1817 list: list.into_var(),
1818 item_fn: item_fn.into_var(),
1819 view: ui_vec![],
1820 }
1821 .into_node()
1822}
1823
1824pub fn list_presenter_from_node<D>(list: impl IntoVar<D>, list_fn: impl IntoVar<WidgetFn<D>>) -> UiNode
1828where
1829 D: VarValue,
1830{
1831 Presenter {
1832 data: list.into_var(),
1833 wgt_fn: list_fn.into_var(),
1834 child: ui_vec![].into_node(),
1835 }
1836 .into_node()
1837}
1838
1839struct Presenter<D>
1840where
1841 D: VarValue,
1842{
1843 data: Var<D>,
1844 wgt_fn: Var<WidgetFn<D>>,
1845 child: UiNode,
1846}
1847impl<D> Presenter<D>
1848where
1849 D: VarValue,
1850{
1851 fn on_update(&mut self) -> bool {
1852 if self.data.is_new() || self.wgt_fn.is_new() {
1853 let was_list = self.child.is_list();
1854
1855 self.child.deinit();
1856
1857 let new_child = self.wgt_fn.get()(self.data.get());
1858 if was_list {
1859 if !new_child.is_list() {
1860 #[cfg(debug_assertions)]
1861 tracing::warn!("presenter changed to !is_list, will convert to list");
1862 }
1863 self.child = new_child.into_list();
1864 } else {
1865 #[cfg(debug_assertions)]
1866 if self.child.is_list() {
1867 tracing::warn!("presenter changed to is_list, likely only first entry node will be used");
1868 }
1869 self.child = new_child;
1870 }
1871
1872 self.child.init();
1873 WIDGET.update_info().layout().render();
1874 true
1875 } else {
1876 false
1877 }
1878 }
1879}
1880impl<D> UiNodeImpl for Presenter<D>
1881where
1882 D: VarValue,
1883{
1884 fn children_len(&self) -> usize {
1885 self.child.children_len()
1886 }
1887
1888 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
1889 self.child.with_child(index, visitor)
1890 }
1891
1892 fn is_list(&self) -> bool {
1893 self.child.is_list()
1894 }
1895
1896 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
1897 self.child.as_dyn().for_each_child(visitor);
1898 }
1899
1900 fn try_for_each_child(
1901 &mut self,
1902 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<BoxAnyVarValue>,
1903 ) -> std::ops::ControlFlow<BoxAnyVarValue> {
1904 self.child.as_dyn().try_for_each_child(visitor)
1905 }
1906
1907 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
1908 self.child.as_dyn().par_each_child(visitor);
1909 }
1910
1911 fn par_fold_reduce(
1912 &mut self,
1913 identity: BoxAnyVarValue,
1914 fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
1915 reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
1916 ) -> BoxAnyVarValue {
1917 self.child.as_dyn().par_fold_reduce(identity, fold, reduce)
1918 }
1919
1920 fn init(&mut self) {
1921 WIDGET.sub_var(&self.data).sub_var(&self.wgt_fn);
1922 self.child = self.wgt_fn.get()(self.data.get());
1923 self.child.init();
1924 }
1925
1926 fn deinit(&mut self) {
1927 self.child.deinit();
1928 if self.child.is_list() {
1929 self.child = ui_vec![].into_node();
1930 } else {
1931 self.child = UiNode::nil();
1932 }
1933 }
1934
1935 fn info(&mut self, info: &mut zng_app::widget::info::WidgetInfoBuilder) {
1936 self.child.info(info);
1937 }
1938
1939 fn update(&mut self, updates: &WidgetUpdates) {
1940 if !self.on_update() {
1941 self.child.update(updates);
1942 }
1943 }
1944
1945 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
1946 if self.on_update() {
1947 observer.reset();
1948 } else {
1949 self.child.as_dyn().update_list(updates, observer);
1950 }
1951 }
1952
1953 fn measure(&mut self, wm: &mut zng_app::widget::info::WidgetMeasure) -> PxSize {
1954 self.child.as_dyn().measure(wm)
1955 }
1956
1957 fn measure_list(
1958 &mut self,
1959 wm: &mut zng_app::widget::info::WidgetMeasure,
1960 measure: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetMeasure) -> PxSize + Sync),
1961 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
1962 ) -> PxSize {
1963 self.child.as_dyn().measure_list(wm, measure, fold_size)
1964 }
1965
1966 fn layout(&mut self, wl: &mut zng_app::widget::info::WidgetLayout) -> PxSize {
1967 self.child.as_dyn().layout(wl)
1968 }
1969
1970 fn layout_list(
1971 &mut self,
1972 wl: &mut zng_app::widget::info::WidgetLayout,
1973 layout: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetLayout) -> PxSize + Sync),
1974 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
1975 ) -> PxSize {
1976 self.child.as_dyn().layout_list(wl, layout, fold_size)
1977 }
1978
1979 fn render(&mut self, frame: &mut FrameBuilder) {
1980 self.child.as_dyn().render(frame);
1981 }
1982
1983 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
1984 self.child.as_dyn().render_list(frame, render);
1985 }
1986
1987 fn render_update(&mut self, update: &mut zng_app::render::FrameUpdate) {
1988 self.child.as_dyn().render_update(update);
1989 }
1990
1991 fn render_update_list(
1992 &mut self,
1993 update: &mut zng_app::render::FrameUpdate,
1994 render_update: &(dyn Fn(usize, &mut UiNode, &mut zng_app::render::FrameUpdate) + Sync),
1995 ) {
1996 self.child.as_dyn().render_update_list(update, render_update);
1997 }
1998
1999 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2000 self.child.as_dyn().as_widget()
2001 }
2002}
2003
2004struct ListPresenter<D>
2005where
2006 D: VarValue,
2007{
2008 list: Var<ObservableVec<D>>,
2009 item_fn: Var<WidgetFn<D>>,
2010 view: UiVec,
2011}
2012
2013impl<D> UiNodeImpl for ListPresenter<D>
2014where
2015 D: VarValue,
2016{
2017 fn children_len(&self) -> usize {
2018 self.view.len()
2019 }
2020
2021 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
2022 self.view.with_child(index, visitor)
2023 }
2024
2025 fn is_list(&self) -> bool {
2026 true
2027 }
2028
2029 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
2030 self.view.for_each_child(visitor);
2031 }
2032
2033 fn try_for_each_child(
2034 &mut self,
2035 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<BoxAnyVarValue>,
2036 ) -> std::ops::ControlFlow<BoxAnyVarValue> {
2037 self.view.try_for_each_child(visitor)
2038 }
2039
2040 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
2041 self.view.par_each_child(visitor);
2042 }
2043
2044 fn par_fold_reduce(
2045 &mut self,
2046 identity: BoxAnyVarValue,
2047 fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
2048 reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
2049 ) -> BoxAnyVarValue {
2050 self.view.par_fold_reduce(identity, fold, reduce)
2051 }
2052
2053 fn init(&mut self) {
2054 debug_assert!(self.view.is_empty());
2055 self.view.clear();
2056
2057 WIDGET.sub_var(&self.list).sub_var(&self.item_fn);
2058
2059 let e_fn = self.item_fn.get();
2060 self.list.with(|l| {
2061 for el in l.iter() {
2062 let child = e_fn(el.clone());
2063 self.view.push(child);
2064 }
2065 });
2066
2067 self.view.init();
2068 }
2069
2070 fn deinit(&mut self) {
2071 self.view.deinit();
2072 self.view.clear();
2073 }
2074
2075 fn update(&mut self, updates: &WidgetUpdates) {
2076 self.update_list(updates, &mut ());
2077 }
2078
2079 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
2080 let mut need_reset = self.item_fn.is_new();
2081
2082 let is_new = self
2083 .list
2084 .with_new(|l| {
2085 need_reset |= l.changes().is_empty() || l.changes() == [VecChange::Clear];
2086
2087 if need_reset {
2088 return;
2089 }
2090
2091 self.view.update_list(updates, observer);
2093
2094 let e_fn = self.item_fn.get();
2095
2096 for change in l.changes() {
2097 match change {
2098 VecChange::Insert { index, count } => {
2099 for i in *index..(*index + count) {
2100 let mut el = e_fn(l[i].clone());
2101 el.init();
2102 self.view.insert(i, el);
2103 observer.inserted(i);
2104 }
2105 }
2106 VecChange::Remove { index, count } => {
2107 let mut count = *count;
2108 let index = *index;
2109 while count > 0 {
2110 count -= 1;
2111
2112 let mut el = self.view.remove(index);
2113 el.deinit();
2114 observer.removed(index);
2115 }
2116 }
2117 VecChange::Move { from_index, to_index } => {
2118 let el = self.view.remove(*from_index);
2119 self.view.insert(*to_index, el);
2120 observer.moved(*from_index, *to_index);
2121 }
2122 VecChange::Clear => unreachable!(),
2123 }
2124 }
2125 })
2126 .is_some();
2127
2128 if !need_reset && !is_new && self.list.with(|l| l.len() != self.view.len()) {
2129 need_reset = true;
2130 }
2131
2132 if need_reset {
2133 self.view.deinit();
2134 self.view.clear();
2135
2136 let e_fn = self.item_fn.get();
2137 self.list.with(|l| {
2138 for el in l.iter() {
2139 let child = e_fn(el.clone());
2140 self.view.push(child);
2141 }
2142 });
2143
2144 self.view.init();
2145 } else if !is_new {
2146 self.view.update_list(updates, observer);
2147 }
2148 }
2149
2150 fn info(&mut self, info: &mut zng_app::widget::info::WidgetInfoBuilder) {
2151 self.view.info(info);
2152 }
2153
2154 fn measure(&mut self, wm: &mut zng_app::widget::info::WidgetMeasure) -> PxSize {
2155 self.view.measure(wm)
2156 }
2157
2158 fn measure_list(
2159 &mut self,
2160 wm: &mut zng_app::widget::info::WidgetMeasure,
2161 measure: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetMeasure) -> PxSize + Sync),
2162 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2163 ) -> PxSize {
2164 self.view.measure_list(wm, measure, fold_size)
2165 }
2166
2167 fn layout(&mut self, wl: &mut zng_app::widget::info::WidgetLayout) -> PxSize {
2168 self.view.layout(wl)
2169 }
2170
2171 fn layout_list(
2172 &mut self,
2173 wl: &mut zng_app::widget::info::WidgetLayout,
2174 layout: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetLayout) -> PxSize + Sync),
2175 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2176 ) -> PxSize {
2177 self.view.layout_list(wl, layout, fold_size)
2178 }
2179
2180 fn render(&mut self, frame: &mut FrameBuilder) {
2181 self.view.render(frame);
2182 }
2183
2184 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
2185 self.view.render_list(frame, render);
2186 }
2187
2188 fn render_update(&mut self, update: &mut zng_app::render::FrameUpdate) {
2189 self.view.render_update(update);
2190 }
2191
2192 fn render_update_list(
2193 &mut self,
2194 update: &mut zng_app::render::FrameUpdate,
2195 render_update: &(dyn Fn(usize, &mut UiNode, &mut zng_app::render::FrameUpdate) + Sync),
2196 ) {
2197 self.view.render_update_list(update, render_update);
2198 }
2199
2200 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2201 None
2202 }
2203}
2204
2205struct ListPresenterFromIter<D, L>
2206where
2207 D: VarValue,
2208 L: IntoIterator<Item = D> + VarValue,
2209{
2210 list: Var<L>,
2211 item_fn: Var<WidgetFn<D>>,
2212 view: UiVec,
2213}
2214
2215impl<D, L> UiNodeImpl for ListPresenterFromIter<D, L>
2216where
2217 D: VarValue,
2218 L: IntoIterator<Item = D> + VarValue,
2219{
2220 fn children_len(&self) -> usize {
2221 self.view.len()
2222 }
2223
2224 fn with_child(&mut self, index: usize, visitor: &mut dyn FnMut(&mut UiNode)) {
2225 self.view.with_child(index, visitor)
2226 }
2227
2228 fn for_each_child(&mut self, visitor: &mut dyn FnMut(usize, &mut UiNode)) {
2229 self.view.for_each_child(visitor)
2230 }
2231
2232 fn try_for_each_child(
2233 &mut self,
2234 visitor: &mut dyn FnMut(usize, &mut UiNode) -> std::ops::ControlFlow<BoxAnyVarValue>,
2235 ) -> std::ops::ControlFlow<BoxAnyVarValue> {
2236 self.view.try_for_each_child(visitor)
2237 }
2238
2239 fn par_each_child(&mut self, visitor: &(dyn Fn(usize, &mut UiNode) + Sync)) {
2240 self.view.par_each_child(visitor);
2241 }
2242
2243 fn par_fold_reduce(
2244 &mut self,
2245 identity: BoxAnyVarValue,
2246 fold: &(dyn Fn(BoxAnyVarValue, usize, &mut UiNode) -> BoxAnyVarValue + Sync),
2247 reduce: &(dyn Fn(BoxAnyVarValue, BoxAnyVarValue) -> BoxAnyVarValue + Sync),
2248 ) -> BoxAnyVarValue {
2249 self.view.par_fold_reduce(identity, fold, reduce)
2250 }
2251
2252 fn is_list(&self) -> bool {
2253 true
2254 }
2255
2256 fn init(&mut self) {
2257 debug_assert!(self.view.is_empty());
2258 self.view.clear();
2259
2260 WIDGET.sub_var(&self.list).sub_var(&self.item_fn);
2261
2262 let e_fn = self.item_fn.get();
2263
2264 self.view.extend(self.list.get().into_iter().map(&*e_fn));
2265 self.view.init();
2266 }
2267
2268 fn deinit(&mut self) {
2269 self.view.deinit();
2270 self.view.clear();
2271 }
2272
2273 fn update(&mut self, updates: &WidgetUpdates) {
2274 self.update_list(updates, &mut ())
2275 }
2276 fn update_list(&mut self, updates: &WidgetUpdates, observer: &mut dyn UiNodeListObserver) {
2277 if self.list.is_new() || self.item_fn.is_new() {
2278 self.view.deinit();
2279 self.view.clear();
2280 let e_fn = self.item_fn.get();
2281 self.view.extend(self.list.get().into_iter().map(&*e_fn));
2282 self.view.init();
2283 observer.reset();
2284 } else {
2285 self.view.update_list(updates, observer);
2286 }
2287 }
2288
2289 fn info(&mut self, info: &mut zng_app::widget::info::WidgetInfoBuilder) {
2290 self.view.info(info)
2291 }
2292
2293 fn measure(&mut self, wm: &mut zng_app::widget::info::WidgetMeasure) -> PxSize {
2294 self.view.measure(wm)
2295 }
2296
2297 fn measure_list(
2298 &mut self,
2299 wm: &mut zng_app::widget::info::WidgetMeasure,
2300 measure: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetMeasure) -> PxSize + Sync),
2301 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2302 ) -> PxSize {
2303 self.view.measure_list(wm, measure, fold_size)
2304 }
2305
2306 fn layout(&mut self, wl: &mut zng_app::widget::info::WidgetLayout) -> PxSize {
2307 self.view.layout(wl)
2308 }
2309
2310 fn layout_list(
2311 &mut self,
2312 wl: &mut zng_app::widget::info::WidgetLayout,
2313 layout: &(dyn Fn(usize, &mut UiNode, &mut zng_app::widget::info::WidgetLayout) -> PxSize + Sync),
2314 fold_size: &(dyn Fn(PxSize, PxSize) -> PxSize + Sync),
2315 ) -> PxSize {
2316 self.view.layout_list(wl, layout, fold_size)
2317 }
2318
2319 fn render(&mut self, frame: &mut FrameBuilder) {
2320 self.view.render(frame);
2321 }
2322
2323 fn render_list(&mut self, frame: &mut FrameBuilder, render: &(dyn Fn(usize, &mut UiNode, &mut FrameBuilder) + Sync)) {
2324 self.view.render_list(frame, render);
2325 }
2326
2327 fn render_update(&mut self, update: &mut zng_app::render::FrameUpdate) {
2328 self.view.render_update(update);
2329 }
2330
2331 fn render_update_list(
2332 &mut self,
2333 update: &mut zng_app::render::FrameUpdate,
2334 render_update: &(dyn Fn(usize, &mut UiNode, &mut zng_app::render::FrameUpdate) + Sync),
2335 ) {
2336 self.view.render_update_list(update, render_update);
2337 }
2338
2339 fn as_widget(&mut self) -> Option<&mut dyn WidgetUiNodeImpl> {
2340 None
2341 }
2342}
2343
2344pub trait VarPresent<D: VarValue> {
2346 fn present(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2348}
2349impl<D: VarValue> VarPresent<D> for Var<D> {
2350 fn present(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2351 presenter(self.clone(), wgt_fn)
2352 }
2353}
2354
2355pub trait VarPresentOpt<D: VarValue> {
2357 fn present_opt(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2359}
2360impl<D: VarValue> VarPresentOpt<D> for Var<Option<D>> {
2361 fn present_opt(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2362 presenter_opt(self.clone(), wgt_fn)
2363 }
2364}
2365
2366pub trait VarPresentList<D: VarValue> {
2368 fn present_list(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2370}
2371impl<D: VarValue> VarPresentList<D> for Var<ObservableVec<D>> {
2372 fn present_list(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2373 list_presenter(self.clone(), wgt_fn)
2374 }
2375}
2376
2377pub trait VarPresentListFromIter<D: VarValue, L: IntoIterator<Item = D> + VarValue> {
2379 fn present_list_from_iter(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode;
2381}
2382impl<D: VarValue, L: IntoIterator<Item = D> + VarValue> VarPresentListFromIter<D, L> for Var<L> {
2383 fn present_list_from_iter(&self, wgt_fn: impl IntoVar<WidgetFn<D>>) -> UiNode {
2384 list_presenter_from_iter(self.clone(), wgt_fn)
2385 }
2386}
2387
2388pub trait VarPresentListFromNode<L: VarValue> {
2390 fn present_list_from_node(&self, list_fn: impl IntoVar<WidgetFn<L>>) -> UiNode;
2392}
2393impl<L: VarValue> VarPresentListFromNode<L> for Var<L> {
2394 fn present_list_from_node(&self, list_fn: impl IntoVar<WidgetFn<L>>) -> UiNode {
2395 list_presenter_from_node(self.clone(), list_fn)
2396 }
2397}
2398
2399pub trait VarPresentData<D: VarValue> {
2401 fn present_data(&self, data: impl IntoVar<D>) -> UiNode;
2403}
2404impl<D: VarValue> VarPresentData<D> for Var<WidgetFn<D>> {
2405 fn present_data(&self, data: impl IntoVar<D>) -> UiNode {
2406 presenter(data, self.clone())
2407 }
2408}