1use crate::{handler::WidgetHandler, widget::node::WhenUiNodeListBuilder};
4use std::{
5 any::{Any, TypeId},
6 collections::{HashMap, hash_map},
7 fmt, ops,
8 sync::Arc,
9};
10
11#[doc(hidden)]
12pub use zng_var::{getter_var, state_var};
13
14#[macro_export]
18macro_rules! source_location {
19 () => {
20 $crate::widget::builder::SourceLocation {
21 file: std::file!(),
22 line: std::line!(),
23 column: std::column!(),
24 }
25 };
26}
27#[doc(inline)]
28pub use crate::source_location;
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
36pub struct SourceLocation {
37 pub file: &'static str,
39 pub line: u32,
41 pub column: u32,
43}
44impl fmt::Display for SourceLocation {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 write!(f, "{}:{}:{}", self.file, self.line, self.column)
47 }
48}
49
50#[doc(hidden)]
51pub fn when_condition_expr_var(expr_var: impl Var<bool>) -> BoxedVar<bool> {
52 expr_var.boxed()
53}
54
55#[doc(hidden)]
56pub struct WgtInfo;
57impl WidgetExt for WgtInfo {
58 fn ext_property__(&mut self, _: Box<dyn PropertyArgs>) {
59 panic!("WgtInfo is for extracting info only")
60 }
61
62 fn ext_property_unset__(&mut self, _: PropertyId) {
63 panic!("WgtInfo is for extracting info only")
64 }
65}
66
67#[macro_export]
100macro_rules! property_id {
101 ($($tt:tt)*) => {
102 $crate::widget::property_meta!($($tt)*).id()
103 }
104}
105#[doc(inline)]
106pub use crate::property_id;
107
108#[macro_export]
135macro_rules! property_info {
136 ($($property:ident)::+ <$($generics:ty),*>) => {
137 $crate::widget::property_meta!($($property)::+).info::<$($generics),*>()
138 };
139 ($($tt:tt)*) => {
140 $crate::widget::property_meta!($($tt)*).info()
141 }
142}
143#[doc(inline)]
144pub use crate::property_info;
145
146#[macro_export]
155macro_rules! property_input_types {
156 ($($tt:tt)*) => {
157 $crate::widget::property_meta!($($tt)*).input_types()
158 }
159}
160#[doc(inline)]
161pub use crate::property_input_types;
162
163#[macro_export]
181macro_rules! property_args {
182 ($($property:ident)::+ = $($value:tt)*) => {
183 {
184 $crate::widget::builder::PropertyArgsGetter! {
185 $($property)::+ = $($value)*
186 }
187 }
188 };
189 ($($property:ident)::+ ::<$($generics:ty),*> = $($value:tt)*) => {
190 {
191 $crate::widget::builder::PropertyArgsGetter! {
192 $($property)::+ ::<$($generics),*> = $($value)*
193 }
194 }
195 };
196 ($property:ident $(;)?) => {
197 {
198 $crate::widget::builder::PropertyArgsGetter! {
199 $property
200 }
201 }
202 }
203}
204#[doc(inline)]
205pub use crate::property_args;
206
207#[macro_export]
209macro_rules! widget_type {
210 ($($widget:ident)::+) => {
211 $($widget)::+::widget_type()
212 };
213}
214use parking_lot::Mutex;
215#[doc(inline)]
216pub use widget_type;
217use zng_app_context::context_local;
218use zng_app_proc_macros::widget;
219use zng_txt::{Txt, formatx};
220use zng_unique_id::{IdEntry, IdMap, IdSet, unique_id_32};
221use zng_var::{
222 AnyVar, AnyVarValue, BoxedAnyVar, BoxedVar, ContextInitHandle, IntoValue, IntoVar, LocalVar, Var, VarValue, impl_from_and_into_var,
223 types::{AnyWhenVarBuilder, ContextualizedVar, WeakContextInitHandle},
224};
225
226use super::{
227 base::{WidgetBase, WidgetExt},
228 node::{
229 ArcNode, ArcNodeList, BoxedUiNode, BoxedUiNodeList, FillUiNode, UiNode, UiNodeList, WhenUiNodeBuilder, with_new_context_init_id,
230 },
231};
232
233#[doc(hidden)]
234#[widget($crate::widget::builder::PropertyArgsGetter)]
235pub struct PropertyArgsGetter(WidgetBase);
236impl PropertyArgsGetter {
237 pub fn widget_build(&mut self) -> Box<dyn PropertyArgs> {
238 let mut wgt = self.widget_take();
239 if !wgt.p.items.is_empty() {
240 if wgt.p.items.len() > 1 {
241 tracing::error!("properties ignored, `property_args!` only collects args for first property");
242 }
243 match wgt.p.items.remove(0).item {
244 WidgetItem::Property { args, .. } => args,
245 WidgetItem::Intrinsic { .. } => unreachable!(),
246 }
247 } else if wgt.unset.is_empty() {
248 panic!("missing property");
249 } else {
250 panic!("cannot use `unset!` in `property_args!`")
251 }
252 }
253}
254
255#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize)]
259pub struct NestPosition {
260 pub group: NestGroup,
262 pub index: u16,
264}
265impl NestPosition {
266 pub const INTRINSIC_INDEX: u16 = u16::MAX / 3;
268
269 pub const PROPERTY_INDEX: u16 = Self::INTRINSIC_INDEX * 2;
271
272 pub fn property(group: NestGroup) -> Self {
274 NestPosition {
275 group,
276 index: Self::PROPERTY_INDEX,
277 }
278 }
279
280 pub fn intrinsic(group: NestGroup) -> Self {
282 NestPosition {
283 group,
284 index: Self::INTRINSIC_INDEX,
285 }
286 }
287}
288impl fmt::Debug for NestPosition {
289 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290 struct IndexName(u16);
291 impl fmt::Debug for IndexName {
292 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
293 match self.0 {
294 NestPosition::INTRINSIC_INDEX => write!(f, "INTRINSIC_INDEX"),
295 NestPosition::PROPERTY_INDEX => write!(f, "PROPERTY_INDEX"),
296 i => write!(f, "{i}"),
297 }
298 }
299 }
300
301 f.debug_struct("NestPosition")
302 .field("group", &self.group)
303 .field("index", &IndexName(self.index))
304 .finish()
305 }
306}
307
308macro_rules! nest_group_items {
309 () => {
310 pub const WIDGET: NestGroup = NestGroup(0);
314
315 pub const CONTEXT: NestGroup = NestGroup(NestGroup::NEXT_GROUP);
322 pub const EVENT: NestGroup = NestGroup(NestGroup::CONTEXT.0 + NestGroup::NEXT_GROUP);
330 pub const LAYOUT: NestGroup = NestGroup(NestGroup::EVENT.0 + NestGroup::NEXT_GROUP);
335
336 pub const SIZE: NestGroup = NestGroup(NestGroup::LAYOUT.0 + NestGroup::NEXT_GROUP);
341
342 pub const WIDGET_INNER: NestGroup = NestGroup(NestGroup::SIZE.0 + NestGroup::NEXT_GROUP);
348
349 pub const BORDER: NestGroup = NestGroup(NestGroup::WIDGET_INNER.0 + NestGroup::NEXT_GROUP);
356 pub const FILL: NestGroup = NestGroup(NestGroup::BORDER.0 + NestGroup::NEXT_GROUP);
361 pub const CHILD_CONTEXT: NestGroup = NestGroup(NestGroup::FILL.0 + NestGroup::NEXT_GROUP);
364 pub const CHILD_LAYOUT: NestGroup = NestGroup(NestGroup::CHILD_CONTEXT.0 + NestGroup::NEXT_GROUP);
368
369 pub const CHILD: NestGroup = NestGroup(u16::MAX);
374 };
375}
376
377#[doc(hidden)]
378pub mod nest_group_items {
379 use super::NestGroup;
383
384 nest_group_items!();
385}
386
387#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
394pub struct NestGroup(u16);
395impl NestGroup {
396 const NEXT_GROUP: u16 = u16::MAX / 10;
397
398 nest_group_items!();
399
400 pub const ITEMS: [Self; 11] = [
405 Self::WIDGET,
406 Self::CONTEXT,
407 Self::EVENT,
408 Self::LAYOUT,
409 Self::SIZE,
410 Self::WIDGET_INNER,
411 Self::BORDER,
412 Self::FILL,
413 Self::CHILD_CONTEXT,
414 Self::CHILD_LAYOUT,
415 Self::CHILD,
416 ];
417
418 fn exact_name(self) -> &'static str {
419 if self.0 == Self::WIDGET.0 {
420 "WIDGET"
421 } else if self.0 == Self::CONTEXT.0 {
422 "CONTEXT"
423 } else if self.0 == Self::EVENT.0 {
424 "EVENT"
425 } else if self.0 == Self::LAYOUT.0 {
426 "LAYOUT"
427 } else if self.0 == Self::SIZE.0 {
428 "SIZE"
429 } else if self.0 == Self::WIDGET_INNER.0 {
430 "WIDGET_INNER"
431 } else if self.0 == Self::BORDER.0 {
432 "BORDER"
433 } else if self.0 == Self::FILL.0 {
434 "FILL"
435 } else if self.0 == Self::CHILD_CONTEXT.0 {
436 "CHILD_CONTEXT"
437 } else if self.0 == Self::CHILD_LAYOUT.0 {
438 "CHILD_LAYOUT"
439 } else if self.0 == Self::CHILD.0 {
440 "CHILD"
441 } else {
442 ""
443 }
444 }
445
446 pub fn name(self) -> Txt {
448 let name = self.exact_name();
449 if name.is_empty() {
450 let closest = Self::ITEMS
451 .into_iter()
452 .min_by_key(|i| ((self.0 as i32 - i.0 as i32).abs()))
453 .unwrap();
454 let diff = self.0 as i32 - closest.0 as i32;
455
456 let name = closest.exact_name();
457 debug_assert!(!name.is_empty());
458
459 formatx!("{closest}{diff:+}")
460 } else {
461 Txt::from_static(name)
462 }
463 }
464}
465impl fmt::Debug for NestGroup {
466 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467 if f.alternate() {
468 write!(f, "NestGroup::")?;
469 }
470 write!(f, "{}", self.name())
471 }
472}
473impl fmt::Display for NestGroup {
474 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
475 write!(f, "{}", self.name())
476 }
477}
478impl ops::Add<i16> for NestGroup {
479 type Output = Self;
480
481 fn add(self, rhs: i16) -> Self::Output {
482 let r = (self.0 as i32) + rhs as i32;
483
484 Self(r.clamp(0, u16::MAX as i32) as u16)
485 }
486}
487impl ops::Sub<i16> for NestGroup {
488 type Output = Self;
489
490 fn sub(self, rhs: i16) -> Self::Output {
491 let r = (self.0 as i32) - rhs as i32;
492
493 Self(r.clamp(0, u16::MAX as i32) as u16)
494 }
495}
496impl ops::AddAssign<i16> for NestGroup {
497 fn add_assign(&mut self, rhs: i16) {
498 *self = *self + rhs;
499 }
500}
501impl ops::SubAssign<i16> for NestGroup {
502 fn sub_assign(&mut self, rhs: i16) {
503 *self = *self - rhs;
504 }
505}
506#[test]
507fn nest_group_spacing() {
508 let mut expected = NestGroup::NEXT_GROUP;
509 for g in &NestGroup::ITEMS[1..NestGroup::ITEMS.len() - 1] {
510 assert_eq!(expected, g.0);
511 expected += NestGroup::NEXT_GROUP;
512 }
513 assert_eq!(expected, (u16::MAX / 10) * 10); }
515#[derive(serde::Deserialize)]
516#[serde(untagged)]
517enum NestGroupSerde<'s> {
518 Named(&'s str),
519 Unnamed(u16),
520}
521impl serde::Serialize for NestGroup {
522 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
523 where
524 S: serde::Serializer,
525 {
526 if serializer.is_human_readable() {
527 self.name().serialize(serializer)
528 } else {
529 self.0.serialize(serializer)
530 }
531 }
532}
533impl<'de> serde::Deserialize<'de> for NestGroup {
534 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
535 where
536 D: serde::Deserializer<'de>,
537 {
538 use serde::de::Error;
539
540 match NestGroupSerde::deserialize(deserializer)? {
541 NestGroupSerde::Named(n) => match n.parse() {
542 Ok(g) => Ok(g),
543 Err(e) => Err(D::Error::custom(e)),
544 },
545 NestGroupSerde::Unnamed(i) => Ok(NestGroup(i)),
546 }
547 }
548}
549impl std::str::FromStr for NestGroup {
550 type Err = String;
551
552 fn from_str(s: &str) -> Result<Self, Self::Err> {
553 let mut name = s;
554 let mut add = 0i16;
555
556 if let Some((n, a)) = s.split_once('+') {
557 add = a.parse().map_err(|e| format!("{e}"))?;
558 name = n;
559 } else if let Some((n, s)) = s.split_once('-') {
560 add = -s.parse().map_err(|e| format!("{e}"))?;
561 name = n;
562 }
563
564 match name {
565 "WIDGET" => Ok(NestGroup::WIDGET + add),
566 "CONTEXT" => Ok(NestGroup::CONTEXT + add),
567 "EVENT" => Ok(NestGroup::EVENT + add),
568 "LAYOUT" => Ok(NestGroup::LAYOUT + add),
569 "SIZE" => Ok(NestGroup::SIZE + add),
570 "BORDER" => Ok(NestGroup::BORDER + add),
571 "FILL" => Ok(NestGroup::FILL + add),
572 "CHILD_CONTEXT" => Ok(NestGroup::CHILD_CONTEXT + add),
573 "CHILD_LAYOUT" => Ok(NestGroup::CHILD_LAYOUT + add),
574 "CHILD" => Ok(NestGroup::CHILD + add),
575 ukn => Err(format!("unknown nest group {ukn:?}")),
576 }
577 }
578}
579
580#[derive(PartialEq, Eq, Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
582pub enum InputKind {
583 Var,
585 Value,
587 UiNode,
589 UiNodeList,
591 WidgetHandler,
593}
594
595#[derive(Clone)]
604pub struct ArcWidgetHandler<A: Clone + 'static>(Arc<Mutex<dyn WidgetHandler<A>>>);
605impl<A: Clone + 'static> ArcWidgetHandler<A> {
606 pub fn new(handler: impl WidgetHandler<A>) -> Self {
608 Self(Arc::new(Mutex::new(handler)))
609 }
610}
611impl<A: Clone + 'static> WidgetHandler<A> for ArcWidgetHandler<A> {
612 fn event(&mut self, args: &A) -> bool {
613 self.0.lock().event(args)
614 }
615
616 fn update(&mut self) -> bool {
617 self.0.lock().update()
618 }
619}
620
621pub trait AnyArcWidgetHandler: Any {
623 fn as_any(&self) -> &dyn Any;
625
626 fn into_any(self: Box<Self>) -> Box<dyn Any>;
628
629 fn clone_boxed(&self) -> Box<dyn AnyArcWidgetHandler>;
631}
632impl<A: Clone + 'static> AnyArcWidgetHandler for ArcWidgetHandler<A> {
633 fn clone_boxed(&self) -> Box<dyn AnyArcWidgetHandler> {
634 Box::new(self.clone())
635 }
636
637 fn as_any(&self) -> &dyn Any {
638 self
639 }
640
641 fn into_any(self: Box<Self>) -> Box<dyn Any> {
642 self
643 }
644}
645
646pub struct AnyWhenArcWidgetHandlerBuilder {
650 default: Box<dyn AnyArcWidgetHandler>,
651 conditions: Vec<(BoxedVar<bool>, Box<dyn AnyArcWidgetHandler>)>,
652}
653impl AnyWhenArcWidgetHandlerBuilder {
654 pub fn new(default: Box<dyn AnyArcWidgetHandler>) -> Self {
656 Self {
657 default,
658 conditions: vec![],
659 }
660 }
661
662 pub fn push(&mut self, condition: BoxedVar<bool>, handler: Box<dyn AnyArcWidgetHandler>) {
664 self.conditions.push((condition, handler));
665 }
666
667 pub fn build<A: Clone + 'static>(self) -> ArcWidgetHandler<A> {
669 match self.default.into_any().downcast::<ArcWidgetHandler<A>>() {
670 Ok(default) => {
671 let mut conditions = Vec::with_capacity(self.conditions.len());
672 for (c, h) in self.conditions {
673 match h.into_any().downcast::<ArcWidgetHandler<A>>() {
674 Ok(h) => conditions.push((c, *h)),
675 Err(_) => continue,
676 }
677 }
678 ArcWidgetHandler::new(WhenWidgetHandler {
679 default: *default,
680 conditions,
681 })
682 }
683 Err(_) => panic!("unexpected build type in widget handler when builder"),
684 }
685 }
686}
687
688struct WhenWidgetHandler<A: Clone + 'static> {
689 default: ArcWidgetHandler<A>,
690 conditions: Vec<(BoxedVar<bool>, ArcWidgetHandler<A>)>,
691}
692impl<A: Clone + 'static> WidgetHandler<A> for WhenWidgetHandler<A> {
693 fn event(&mut self, args: &A) -> bool {
694 for (c, h) in &mut self.conditions {
695 if c.get() {
696 return h.event(args);
697 }
698 }
699 self.default.event(args)
700 }
701
702 fn update(&mut self) -> bool {
703 let mut pending = self.default.update();
704 for (_, h) in &mut self.conditions {
705 pending |= h.update();
706 }
707 pending
708 }
709}
710
711pub type PropertyBuildActions = Vec<Vec<Box<dyn AnyPropertyBuildAction>>>;
715
716pub type PropertyBuildActionsWhenData = Vec<Vec<Option<WhenBuildActionData>>>;
720
721pub struct PropertyNewArgs {
723 pub args: Vec<Box<dyn Any>>,
744
745 pub build_actions: PropertyBuildActions,
766
767 pub build_actions_when_data: PropertyBuildActionsWhenData,
773}
774
775#[derive(Debug, Clone)]
779pub struct PropertyInfo {
780 pub group: NestGroup,
782 pub capture: bool,
786
787 pub id: PropertyId,
789 pub name: &'static str,
791
792 pub location: SourceLocation,
794
795 pub default: Option<fn() -> Box<dyn PropertyArgs>>,
799
800 pub new: fn(PropertyNewArgs) -> Box<dyn PropertyArgs>,
810
811 pub inputs: Box<[PropertyInput]>,
813}
814impl PropertyInfo {
815 pub fn input_idx(&self, name: &str) -> Option<usize> {
817 self.inputs.iter().position(|i| i.name == name)
818 }
819}
820
821#[derive(Debug, Clone)]
823pub struct PropertyInput {
824 pub name: &'static str,
826 pub kind: InputKind,
828 pub ty: TypeId,
830 pub ty_name: &'static str,
832}
833impl PropertyInput {
834 pub fn display_ty_name(&self) -> Txt {
838 pretty_type_name::pretty_type_name_str(self.ty_name).into()
839 }
840}
841
842pub trait PropertyArgs: Send + Sync {
844 fn clone_boxed(&self) -> Box<dyn PropertyArgs>;
846
847 fn property(&self) -> PropertyInfo;
849
850 fn var(&self, i: usize) -> &dyn AnyVar {
854 panic_input(&self.property(), i, InputKind::Var)
855 }
856
857 fn value(&self, i: usize) -> &dyn AnyVarValue {
859 panic_input(&self.property(), i, InputKind::Value)
860 }
861
862 fn ui_node(&self, i: usize) -> &ArcNode<BoxedUiNode> {
864 panic_input(&self.property(), i, InputKind::UiNode)
865 }
866
867 fn ui_node_list(&self, i: usize) -> &ArcNodeList<BoxedUiNodeList> {
869 panic_input(&self.property(), i, InputKind::UiNodeList)
870 }
871
872 fn widget_handler(&self, i: usize) -> &dyn AnyArcWidgetHandler {
876 panic_input(&self.property(), i, InputKind::WidgetHandler)
877 }
878
879 fn instantiate(&self, child: BoxedUiNode) -> BoxedUiNode;
883}
884impl dyn PropertyArgs + '_ {
885 pub fn id(&self) -> PropertyId {
887 self.property().id
888 }
889
890 pub fn downcast_value<T>(&self, i: usize) -> &T
896 where
897 T: VarValue,
898 {
899 self.value(i).as_any().downcast_ref::<T>().expect("cannot downcast value to type")
900 }
901 pub fn downcast_var<T>(&self, i: usize) -> &BoxedVar<T>
907 where
908 T: VarValue,
909 {
910 self.var(i)
911 .as_any()
912 .downcast_ref::<BoxedVar<T>>()
913 .expect("cannot downcast var to type")
914 }
915
916 pub fn downcast_handler<A>(&self, i: usize) -> &ArcWidgetHandler<A>
922 where
923 A: 'static + Clone,
924 {
925 self.widget_handler(i)
926 .as_any()
927 .downcast_ref::<ArcWidgetHandler<A>>()
928 .expect("cannot downcast handler to type")
929 }
930
931 pub fn live_debug(&self, i: usize) -> BoxedVar<Txt> {
937 let p = self.property();
938 match p.inputs[i].kind {
939 InputKind::Var => self.var(i).map_debug(),
940 InputKind::Value => LocalVar(formatx!("{:?}", self.value(i))).boxed(),
941 InputKind::UiNode => LocalVar(Txt::from_static("<impl UiNode>")).boxed(),
942 InputKind::UiNodeList => LocalVar(Txt::from_static("<impl UiNodeList>")).boxed(),
943 InputKind::WidgetHandler => LocalVar(formatx!("<impl WidgetHandler<{}>>", p.inputs[i].display_ty_name())).boxed(),
944 }
945 }
946
947 pub fn debug(&self, i: usize) -> Txt {
951 let p = self.property();
952 match p.inputs[i].kind {
953 InputKind::Var => formatx!("{:?}", self.var(i).get_any()),
954 InputKind::Value => formatx!("{:?}", self.value(i)),
955 InputKind::UiNode => Txt::from_static("<impl UiNode>"),
956 InputKind::UiNodeList => Txt::from_static("<impl UiNodeList>"),
957 InputKind::WidgetHandler => formatx!("<impl WidgetHandler<{}>>", p.inputs[i].display_ty_name()),
958 }
959 }
960
961 pub fn new_build(
965 &self,
966 build_actions: PropertyBuildActions,
967 build_actions_when_data: PropertyBuildActionsWhenData,
968 ) -> Box<dyn PropertyArgs> {
969 let p = self.property();
970
971 let mut args: Vec<Box<dyn Any>> = Vec::with_capacity(p.inputs.len());
972 for (i, input) in p.inputs.iter().enumerate() {
973 match input.kind {
974 InputKind::Var => args.push(self.var(i).clone_any().double_boxed_any()),
975 InputKind::Value => args.push(self.value(i).clone_boxed().into_any()),
976 InputKind::UiNode => args.push(Box::new(self.ui_node(i).clone())),
977 InputKind::UiNodeList => args.push(Box::new(self.ui_node_list(i).clone())),
978 InputKind::WidgetHandler => args.push(self.widget_handler(i).clone_boxed().into_any()),
979 }
980 }
981
982 (p.new)(PropertyNewArgs {
983 args,
984 build_actions,
985 build_actions_when_data,
986 })
987 }
988}
989
990#[doc(hidden)]
991pub fn panic_input(info: &PropertyInfo, i: usize, kind: InputKind) -> ! {
992 if i > info.inputs.len() {
993 panic!("index out of bounds, the input len is {}, but the index is {i}", info.inputs.len())
994 } else if info.inputs[i].kind != kind {
995 panic!(
996 "invalid input request `{:?}`, but `{}` is `{:?}`",
997 kind, info.inputs[i].name, info.inputs[i].kind
998 )
999 } else {
1000 panic!("invalid input `{}`", info.inputs[i].name)
1001 }
1002}
1003
1004#[doc(hidden)]
1005pub fn var_to_args<T: VarValue>(var: impl IntoVar<T>) -> BoxedVar<T> {
1006 var.into_var().boxed()
1007}
1008
1009#[doc(hidden)]
1010pub fn value_to_args<T: VarValue>(value: impl IntoValue<T>) -> T {
1011 value.into()
1012}
1013
1014#[doc(hidden)]
1015pub fn ui_node_to_args(node: impl UiNode) -> ArcNode<BoxedUiNode> {
1016 ArcNode::new(node.boxed())
1017}
1018
1019#[doc(hidden)]
1020pub fn ui_node_list_to_args(node_list: impl UiNodeList) -> ArcNodeList<BoxedUiNodeList> {
1021 ArcNodeList::new(node_list.boxed())
1022}
1023
1024#[doc(hidden)]
1025pub fn widget_handler_to_args<A: Clone + 'static>(handler: impl WidgetHandler<A>) -> ArcWidgetHandler<A> {
1026 ArcWidgetHandler::new(handler)
1027}
1028
1029#[doc(hidden)]
1030pub fn iter_input_build_actions<'a>(
1031 actions: &'a PropertyBuildActions,
1032 data: &'a PropertyBuildActionsWhenData,
1033 index: usize,
1034) -> impl Iterator<Item = (&'a dyn AnyPropertyBuildAction, &'a [Option<WhenBuildActionData>])> {
1035 let mut actions = actions.iter();
1036 let mut data = data.iter();
1037
1038 std::iter::from_fn(move || {
1039 let action = &*actions.next()?[index];
1040 let data = if let Some(data) = data.next() { &data[..] } else { &[None] };
1041
1042 Some((action, data))
1043 })
1044}
1045
1046fn apply_build_actions<'a, I: Any + Send>(
1047 mut item: I,
1048 mut actions: impl Iterator<Item = (&'a dyn AnyPropertyBuildAction, &'a [Option<WhenBuildActionData>])>,
1049) -> I {
1050 if let Some((action, data)) = actions.next() {
1051 let action = action
1052 .as_any()
1053 .downcast_ref::<PropertyBuildAction<I>>()
1054 .expect("property build action type did not match expected var type");
1055
1056 item = action.build(PropertyBuildActionArgs {
1057 input: item,
1058 when_conditions_data: data,
1059 });
1060 }
1061 item
1062}
1063
1064#[doc(hidden)]
1065pub fn new_dyn_var<'a, T: VarValue>(
1066 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1067 actions: impl Iterator<Item = (&'a dyn AnyPropertyBuildAction, &'a [Option<WhenBuildActionData>])>,
1068) -> BoxedVar<T> {
1069 let item = inputs.next().expect("missing input");
1070
1071 let item = match item.downcast::<AnyWhenVarBuilder>() {
1072 Ok(builder) => builder.build::<T>().expect("invalid when builder").boxed(),
1073 Err(item) => *item.downcast::<BoxedVar<T>>().expect("input did not match expected var types"),
1074 };
1075
1076 apply_build_actions(item, actions)
1077}
1078
1079#[doc(hidden)]
1080pub fn new_dyn_ui_node<'a>(
1081 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1082 actions: impl Iterator<Item = (&'a dyn AnyPropertyBuildAction, &'a [Option<WhenBuildActionData>])>,
1083) -> ArcNode<BoxedUiNode> {
1084 let item = inputs.next().expect("missing input");
1085
1086 let item = match item.downcast::<WhenUiNodeBuilder>() {
1087 Ok(builder) => ArcNode::new(builder.build().boxed()),
1088 Err(item) => *item
1089 .downcast::<ArcNode<BoxedUiNode>>()
1090 .expect("input did not match expected UiNode types"),
1091 };
1092
1093 apply_build_actions(item, actions)
1094}
1095
1096#[doc(hidden)]
1097pub fn new_dyn_ui_node_list<'a>(
1098 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1099 actions: impl Iterator<Item = (&'a dyn AnyPropertyBuildAction, &'a [Option<WhenBuildActionData>])>,
1100) -> ArcNodeList<BoxedUiNodeList> {
1101 let item = inputs.next().expect("missing input");
1102
1103 let item = match item.downcast::<WhenUiNodeListBuilder>() {
1104 Ok(builder) => ArcNodeList::new(builder.build().boxed()),
1105 Err(item) => *item
1106 .downcast::<ArcNodeList<BoxedUiNodeList>>()
1107 .expect("input did not match expected UiNodeList types"),
1108 };
1109
1110 apply_build_actions(item, actions)
1111}
1112
1113#[doc(hidden)]
1114pub fn new_dyn_widget_handler<'a, A: Clone + 'static>(
1115 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1116 actions: impl Iterator<Item = (&'a dyn AnyPropertyBuildAction, &'a [Option<WhenBuildActionData>])>,
1117) -> ArcWidgetHandler<A> {
1118 let item = inputs.next().expect("missing input");
1119
1120 let item = match item.downcast::<AnyWhenArcWidgetHandlerBuilder>() {
1121 Ok(builder) => builder.build(),
1122 Err(item) => *item
1123 .downcast::<ArcWidgetHandler<A>>()
1124 .expect("input did not match expected WidgetHandler types"),
1125 };
1126
1127 apply_build_actions(item, actions)
1128}
1129
1130#[doc(hidden)]
1131pub fn new_dyn_other<'a, T: Any + Send>(
1132 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1133 actions: impl Iterator<Item = (&'a dyn AnyPropertyBuildAction, &'a [Option<WhenBuildActionData>])>,
1134) -> T {
1135 let item = *inputs
1136 .next()
1137 .expect("missing input")
1138 .downcast::<T>()
1139 .expect("input did not match expected var type");
1140
1141 apply_build_actions(item, actions)
1142}
1143
1144#[derive(Clone, PartialEq)]
1148pub struct UiNodeInWhenExprError;
1149impl fmt::Debug for UiNodeInWhenExprError {
1150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1151 write!(f, "{self}")
1152 }
1153}
1154impl fmt::Display for UiNodeInWhenExprError {
1155 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1156 write!(
1157 f,
1158 "cannot ref `impl UiNode` in when expression, only var and value properties allowed"
1159 )
1160 }
1161}
1162impl std::error::Error for UiNodeInWhenExprError {}
1163
1164#[derive(Clone, PartialEq)]
1168pub struct UiNodeListInWhenExprError;
1169impl fmt::Debug for UiNodeListInWhenExprError {
1170 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1171 write!(f, "{self}")
1172 }
1173}
1174impl fmt::Display for UiNodeListInWhenExprError {
1175 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1176 write!(
1177 f,
1178 "cannot ref `impl UiNodeList` in when expression, only var and value properties allowed"
1179 )
1180 }
1181}
1182impl std::error::Error for UiNodeListInWhenExprError {}
1183
1184#[derive(Clone, PartialEq)]
1188pub struct WidgetHandlerInWhenExprError;
1189impl fmt::Debug for WidgetHandlerInWhenExprError {
1190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191 write!(f, "{self}")
1192 }
1193}
1194impl fmt::Display for WidgetHandlerInWhenExprError {
1195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1196 write!(
1197 f,
1198 "cannot ref `impl WidgetHandler<A>` in when expression, only var and value properties allowed"
1199 )
1200 }
1201}
1202impl std::error::Error for WidgetHandlerInWhenExprError {}
1203
1204#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
1212pub struct Importance(pub u32);
1213impl Importance {
1214 pub const WIDGET: Importance = Importance(1000);
1216 pub const INSTANCE: Importance = Importance(1000 * 10);
1218}
1219impl_from_and_into_var! {
1220 fn from(imp: u32) -> Importance {
1221 Importance(imp)
1222 }
1223}
1224
1225unique_id_32! {
1226 pub struct PropertyId;
1228}
1229zng_unique_id::impl_unique_id_bytemuck!(PropertyId);
1230impl fmt::Debug for PropertyId {
1231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1232 f.debug_tuple("PropertyId").field(&self.get()).finish()
1233 }
1234}
1235
1236#[derive(Clone, Copy, Debug)]
1242pub struct WidgetType {
1243 pub type_id: TypeId,
1245 pub path: &'static str,
1247 pub location: SourceLocation,
1249}
1250impl WidgetType {
1251 pub fn name(&self) -> &'static str {
1253 self.path.rsplit_once(':').map(|(_, n)| n).unwrap_or(self.path)
1254 }
1255}
1256impl PartialEq for WidgetType {
1257 fn eq(&self, other: &Self) -> bool {
1258 self.type_id == other.type_id
1259 }
1260}
1261impl Eq for WidgetType {}
1262impl std::hash::Hash for WidgetType {
1263 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1264 self.type_id.hash(state);
1265 }
1266}
1267
1268#[derive(Clone, Copy, Debug)]
1270pub enum WhenInputMember {
1271 Named(&'static str),
1273 Index(usize),
1275}
1276
1277#[derive(Clone)]
1279pub struct WhenInput {
1280 pub property: PropertyId,
1282 pub member: WhenInputMember,
1284 pub var: WhenInputVar,
1286 pub property_default: Option<fn() -> Box<dyn PropertyArgs>>,
1288}
1289impl fmt::Debug for WhenInput {
1290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1291 f.debug_struct("WhenInput")
1292 .field("property", &self.property)
1293 .field("member", &self.member)
1294 .finish_non_exhaustive()
1295 }
1296}
1297
1298struct WhenInputInitData<T: VarValue> {
1299 data: Vec<(WeakContextInitHandle, BoxedVar<T>)>,
1300}
1301impl<T: VarValue> WhenInputInitData<T> {
1302 const fn empty() -> Self {
1303 Self { data: vec![] }
1304 }
1305 fn get(&mut self) -> BoxedVar<T> {
1306 let current_id = WHEN_INPUT_CONTEXT_INIT_ID.get();
1307 let current_id = current_id.downgrade();
1308
1309 let mut r = None;
1310 self.data.retain(|(id, val)| {
1311 let retain = id.is_alive();
1312 if retain && id == ¤t_id {
1313 r = Some(val.clone());
1314 }
1315 retain
1316 });
1317 match r {
1318 Some(r) => r,
1319 None => {
1320 if !self.data.is_empty() {
1321 tracing::error!("when input not inited");
1322 let last = self.data.len() - 1;
1323 self.data[last].1.clone()
1324 } else {
1325 panic!("when input not inited")
1326 }
1327 }
1328 }
1329 }
1330}
1331context_local! {
1332 static WHEN_INPUT_CONTEXT_INIT_ID: ContextInitHandle = ContextInitHandle::new();
1333}
1334impl<T: VarValue> AnyWhenInputVarInner for WhenInputInitData<T> {
1335 fn as_any(&mut self) -> &mut dyn Any {
1336 self
1337 }
1338
1339 fn set(&mut self, handle: WeakContextInitHandle, var: BoxedAnyVar) {
1340 let var = var
1341 .double_boxed_any()
1342 .downcast::<BoxedVar<T>>()
1343 .expect("incorrect when input var type");
1344
1345 if let Some(i) = self.data.iter().position(|(i, _)| i == &handle) {
1346 self.data[i].1 = var;
1347 } else {
1348 self.data.push((handle, var));
1349 }
1350 }
1351}
1352trait AnyWhenInputVarInner: Any + Send {
1353 fn as_any(&mut self) -> &mut dyn Any;
1354 fn set(&mut self, handle: WeakContextInitHandle, var: BoxedAnyVar);
1355}
1356
1357#[derive(Clone)]
1359pub struct WhenInputVar {
1360 var: Arc<Mutex<dyn AnyWhenInputVarInner>>,
1361}
1362impl WhenInputVar {
1363 pub fn new<T: VarValue>() -> (Self, impl Var<T>) {
1367 let arc: Arc<Mutex<dyn AnyWhenInputVarInner>> = Arc::new(Mutex::new(WhenInputInitData::<T>::empty()));
1368 (
1369 WhenInputVar { var: arc.clone() },
1370 ContextualizedVar::new(move || arc.lock().as_any().downcast_mut::<WhenInputInitData<T>>().unwrap().get()),
1371 )
1372 }
1373
1374 fn set(&self, handle: WeakContextInitHandle, var: BoxedAnyVar) {
1375 self.var.lock().set(handle, var);
1376 }
1377}
1378
1379type WhenBuildActionData = Arc<dyn Any + Send + Sync>;
1380type WhenBuildDefaultAction = Arc<dyn Fn() -> Vec<Box<dyn AnyPropertyBuildAction>> + Send + Sync>;
1381
1382#[derive(Clone)]
1384pub struct WhenBuildAction {
1385 pub data: WhenBuildActionData,
1387 pub default_action: Option<WhenBuildDefaultAction>,
1393}
1394impl WhenBuildAction {
1395 pub fn new<D, F>(data: D, default_action: F) -> Self
1397 where
1398 D: Any + Send + Sync + 'static,
1399 F: Fn() -> Vec<Box<dyn AnyPropertyBuildAction>> + Send + Sync + 'static,
1400 {
1401 Self {
1402 data: Arc::new(data),
1403 default_action: Some(Arc::new(default_action)),
1404 }
1405 }
1406
1407 pub fn new_no_default(data: impl Any + Send + Sync + 'static) -> Self {
1409 Self {
1410 data: Arc::new(data),
1411 default_action: None,
1412 }
1413 }
1414}
1415
1416#[derive(Clone)]
1418pub struct WhenInfo {
1419 pub inputs: Box<[WhenInput]>,
1427
1428 pub state: BoxedVar<bool>,
1432
1433 pub assigns: Vec<Box<dyn PropertyArgs>>,
1436
1437 pub build_action_data: Vec<((PropertyId, &'static str), WhenBuildAction)>,
1439
1440 pub expr: &'static str,
1442
1443 pub location: SourceLocation,
1445}
1446impl fmt::Debug for WhenInfo {
1447 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1448 struct DebugBuildActions<'a>(&'a WhenInfo);
1449 impl fmt::Debug for DebugBuildActions<'_> {
1450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1451 f.debug_list().entries(self.0.build_action_data.iter().map(|(k, _)| k)).finish()
1452 }
1453 }
1454
1455 f.debug_struct("WhenInfo")
1456 .field("inputs", &self.inputs)
1457 .field("state", &self.state.debug())
1458 .field("assigns", &self.assigns)
1459 .field("build_action_data", &DebugBuildActions(self))
1460 .field("expr", &self.expr)
1461 .finish()
1462 }
1463}
1464impl Clone for Box<dyn PropertyArgs> {
1465 fn clone(&self) -> Self {
1466 PropertyArgs::clone_boxed(&**self)
1467 }
1468}
1469impl fmt::Debug for &dyn PropertyArgs {
1470 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1471 f.debug_struct("dyn PropertyArgs")
1472 .field("property", &self.property())
1473 .finish_non_exhaustive()
1474 }
1475}
1476impl fmt::Debug for Box<dyn PropertyArgs> {
1477 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1478 f.debug_struct("dyn PropertyArgs")
1479 .field("property", &self.property())
1480 .finish_non_exhaustive()
1481 }
1482}
1483
1484#[derive(Clone)]
1485struct WidgetItemPositioned {
1486 position: NestPosition,
1487 insert_idx: u32,
1488 item: WidgetItem,
1489}
1490impl WidgetItemPositioned {
1491 fn sort_key(&self) -> (NestPosition, u32) {
1492 (self.position, self.insert_idx)
1493 }
1494}
1495
1496#[derive(Clone, Debug)]
1497struct WhenItemPositioned {
1498 importance: Importance,
1499 insert_idx: u32,
1500 when: WhenInfo,
1501}
1502impl WhenItemPositioned {
1503 fn sort_key(&self) -> (Importance, u32) {
1504 (self.importance, self.insert_idx)
1505 }
1506}
1507
1508enum WidgetItem {
1509 Property {
1510 importance: Importance,
1511 args: Box<dyn PropertyArgs>,
1512 captured: bool,
1513 },
1514 Intrinsic {
1515 name: &'static str,
1516 new: Box<dyn FnOnce(BoxedUiNode) -> BoxedUiNode + Send + Sync>,
1517 },
1518}
1519impl Clone for WidgetItem {
1520 fn clone(&self) -> Self {
1521 match self {
1522 Self::Property {
1523 importance,
1524 args,
1525 captured,
1526 } => Self::Property {
1527 importance: *importance,
1528 captured: *captured,
1529 args: args.clone(),
1530 },
1531 Self::Intrinsic { .. } => unreachable!("only WidgetBuilder clones, and it does not insert intrinsic"),
1532 }
1533 }
1534}
1535
1536type PropertyBuildActionsMap = HashMap<(PropertyId, &'static str), (Importance, Vec<Box<dyn AnyPropertyBuildAction>>)>;
1538type PropertyBuildActionsVec = Vec<((PropertyId, &'static str), (Importance, Vec<Box<dyn AnyPropertyBuildAction>>))>;
1539
1540pub struct WidgetBuilder {
1542 widget_type: WidgetType,
1543
1544 insert_idx: u32,
1545 p: WidgetBuilderProperties,
1546 unset: HashMap<PropertyId, Importance>,
1547
1548 whens: Vec<WhenItemPositioned>,
1549 when_insert_idx: u32,
1550
1551 p_build_actions: PropertyBuildActionsMap,
1552 p_build_actions_unset: HashMap<(PropertyId, &'static str), Importance>,
1553
1554 build_actions: Vec<Arc<Mutex<dyn FnMut(&mut WidgetBuilding) + Send>>>,
1555
1556 custom_build: Option<Arc<Mutex<dyn FnMut(WidgetBuilder) -> BoxedUiNode + Send>>>,
1557}
1558impl Clone for WidgetBuilder {
1559 fn clone(&self) -> Self {
1560 Self {
1561 widget_type: self.widget_type,
1562 p: WidgetBuilderProperties { items: self.items.clone() },
1563 p_build_actions: self.p_build_actions.clone(),
1564 insert_idx: self.insert_idx,
1565 unset: self.unset.clone(),
1566 p_build_actions_unset: self.p_build_actions_unset.clone(),
1567 whens: self.whens.clone(),
1568 when_insert_idx: self.when_insert_idx,
1569 build_actions: self.build_actions.clone(),
1570 custom_build: self.custom_build.clone(),
1571 }
1572 }
1573}
1574impl fmt::Debug for WidgetBuilder {
1575 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1576 struct PropertiesDebug<'a>(&'a WidgetBuilderProperties);
1577 impl fmt::Debug for PropertiesDebug<'_> {
1578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1579 f.debug_list().entries(self.0.properties()).finish()
1580 }
1581 }
1582 f.debug_struct("WidgetBuilder")
1583 .field("widget_type", &self.widget_type)
1584 .field("properties", &PropertiesDebug(&self.p))
1585 .field("unset", &self.unset)
1586 .field("whens", &self.whens)
1587 .field("build_actions.len", &self.build_actions.len())
1588 .field("is_custom_build", &self.is_custom_build())
1589 .finish()
1590 }
1591}
1592impl WidgetBuilder {
1593 pub fn new(widget: WidgetType) -> Self {
1595 Self {
1596 widget_type: widget,
1597 p: WidgetBuilderProperties { items: Default::default() },
1598 insert_idx: 0,
1599 unset: Default::default(),
1600 whens: Default::default(),
1601 p_build_actions: Default::default(),
1602 p_build_actions_unset: Default::default(),
1603 when_insert_idx: 0,
1604 build_actions: Default::default(),
1605 custom_build: Default::default(),
1606 }
1607 }
1608
1609 pub fn widget_type(&self) -> WidgetType {
1611 self.widget_type
1612 }
1613
1614 pub fn push_property(&mut self, importance: Importance, args: Box<dyn PropertyArgs>) {
1618 let pos = NestPosition::property(args.property().group);
1619 self.push_property_positioned(importance, pos, args);
1620 }
1621
1622 pub fn push_property_positioned(&mut self, importance: Importance, position: NestPosition, args: Box<dyn PropertyArgs>) {
1624 self.push_property_positioned_impl(importance, position, args, false)
1625 }
1626 fn push_property_positioned_impl(
1627 &mut self,
1628 importance: Importance,
1629 position: NestPosition,
1630 args: Box<dyn PropertyArgs>,
1631 captured: bool,
1632 ) {
1633 let insert_idx = self.insert_idx;
1634 self.insert_idx = insert_idx.wrapping_add(1);
1635
1636 let property_id = args.id();
1637 if let Some(i) = self.p.property_index(property_id) {
1638 match &self.p.items[i].item {
1639 WidgetItem::Property { importance: imp, .. } => {
1640 if *imp <= importance {
1641 self.p.items[i] = WidgetItemPositioned {
1643 position,
1644 insert_idx,
1645 item: WidgetItem::Property {
1646 importance,
1647 args,
1648 captured,
1649 },
1650 };
1651 }
1652 }
1653 WidgetItem::Intrinsic { .. } => unreachable!(),
1654 }
1655 } else {
1656 if let Some(imp) = self.unset.get(&property_id) {
1657 if *imp >= importance {
1658 return; }
1660 }
1661 self.p.items.push(WidgetItemPositioned {
1662 position,
1663 insert_idx,
1664 item: WidgetItem::Property {
1665 importance,
1666 args,
1667 captured,
1668 },
1669 });
1670 }
1671 }
1672
1673 pub fn push_when(&mut self, importance: Importance, mut when: WhenInfo) {
1675 let insert_idx = self.when_insert_idx;
1676 self.when_insert_idx = insert_idx.wrapping_add(1);
1677
1678 when.assigns.retain(|a| {
1679 if let Some(imp) = self.unset.get(&a.id()) {
1680 *imp < importance
1681 } else {
1682 true
1683 }
1684 });
1685
1686 if !when.assigns.is_empty() {
1687 self.whens.push(WhenItemPositioned {
1688 importance,
1689 insert_idx,
1690 when,
1691 });
1692 }
1693 }
1694
1695 pub fn push_unset(&mut self, importance: Importance, property_id: PropertyId) {
1697 let check;
1698 match self.unset.entry(property_id) {
1699 hash_map::Entry::Occupied(mut e) => {
1700 let i = e.get_mut();
1701 check = *i < importance;
1702 *i = importance;
1703 }
1704 hash_map::Entry::Vacant(e) => {
1705 check = true;
1706 e.insert(importance);
1707 }
1708 }
1709
1710 if check {
1711 if let Some(i) = self.p.property_index(property_id) {
1712 match &self.p.items[i].item {
1713 WidgetItem::Property { importance: imp, .. } => {
1714 if *imp <= importance {
1715 self.p.items.swap_remove(i);
1716 }
1717 }
1718 WidgetItem::Intrinsic { .. } => unreachable!(),
1719 }
1720 }
1721
1722 self.whens.retain_mut(|w| {
1723 if w.importance <= importance {
1724 w.when.assigns.retain(|a| a.id() != property_id);
1725 !w.when.assigns.is_empty()
1726 } else {
1727 true
1728 }
1729 });
1730 }
1731 }
1732
1733 pub fn push_property_build_action(
1738 &mut self,
1739 property_id: PropertyId,
1740 action_name: &'static str,
1741 importance: Importance,
1742 input_actions: Vec<Box<dyn AnyPropertyBuildAction>>,
1743 ) {
1744 match self.p_build_actions.entry((property_id, action_name)) {
1745 hash_map::Entry::Occupied(mut e) => {
1746 if e.get().0 < importance {
1747 e.insert((importance, input_actions));
1748 }
1749 }
1750 hash_map::Entry::Vacant(e) => {
1751 if let Some(imp) = self.p_build_actions_unset.get(&(property_id, action_name)) {
1752 if *imp >= importance {
1753 return;
1755 }
1756 }
1757 e.insert((importance, input_actions));
1758 }
1759 }
1760 }
1761
1762 pub fn push_unset_property_build_action(&mut self, property_id: PropertyId, action_name: &'static str, importance: Importance) {
1766 let mut check = false;
1767 match self.p_build_actions_unset.entry((property_id, action_name)) {
1768 hash_map::Entry::Occupied(mut e) => {
1769 if *e.get() < importance {
1770 e.insert(importance);
1771 check = true;
1772 }
1773 }
1774 hash_map::Entry::Vacant(e) => {
1775 e.insert(importance);
1776 check = true;
1777 }
1778 }
1779 if check {
1780 self.p_build_actions.retain(|_, (imp, _)| *imp > importance);
1781 }
1782 }
1783
1784 pub fn clear_property_build_actions(&mut self) {
1786 self.p_build_actions.clear();
1787 }
1788
1789 pub fn push_build_action(&mut self, action: impl FnMut(&mut WidgetBuilding) + Send + 'static) {
1791 self.build_actions.push(Arc::new(Mutex::new(action)))
1792 }
1793
1794 pub fn clear_build_actions(&mut self) {
1796 self.build_actions.clear();
1797 }
1798
1799 pub fn is_custom_build(&self) -> bool {
1801 self.custom_build.is_some()
1802 }
1803
1804 pub fn set_custom_build<R: UiNode>(&mut self, mut build: impl FnMut(WidgetBuilder) -> R + Send + 'static) {
1811 self.custom_build = Some(Arc::new(Mutex::new(move |b| build(b).boxed())));
1812 }
1813
1814 pub fn clear_custom_build(&mut self) {
1816 self.custom_build = None;
1817 }
1818
1819 pub fn extend(&mut self, other: WidgetBuilder) {
1829 for (id, imp) in other.unset {
1830 self.push_unset(imp, id);
1831 }
1832
1833 for ((id, name), imp) in other.p_build_actions_unset {
1834 self.push_unset_property_build_action(id, name, imp);
1835 }
1836
1837 for WidgetItemPositioned { position, item, .. } in other.p.items {
1838 match item {
1839 WidgetItem::Property {
1840 importance,
1841 args,
1842 captured,
1843 } => {
1844 self.push_property_positioned_impl(importance, position, args, captured);
1845 }
1846 WidgetItem::Intrinsic { .. } => unreachable!(),
1847 }
1848 }
1849
1850 for w in other.whens {
1851 self.push_when(w.importance, w.when);
1852 }
1853
1854 for ((id, name), (imp, action)) in other.p_build_actions {
1855 self.push_property_build_action(id, name, imp, action);
1856 }
1857
1858 for act in other.build_actions {
1859 self.build_actions.push(act);
1860 }
1861
1862 if let Some(c) = other.custom_build {
1863 self.custom_build = Some(c);
1864 }
1865 }
1866
1867 pub fn has_properties(&self) -> bool {
1869 !self.p.items.is_empty()
1870 }
1871
1872 pub fn has_unsets(&self) -> bool {
1874 !self.unset.is_empty()
1875 }
1876
1877 pub fn has_whens(&self) -> bool {
1879 !self.whens.is_empty()
1880 }
1881
1882 pub fn split_off(&mut self, properties: impl IntoIterator<Item = PropertyId>, out: &mut WidgetBuilder) {
1889 self.split_off_impl(properties.into_iter().collect(), out)
1890 }
1891 fn split_off_impl(&mut self, properties: IdSet<PropertyId>, out: &mut WidgetBuilder) {
1892 let mut found = 0;
1893
1894 let mut i = 0;
1896 while i < self.items.len() && found < properties.len() {
1897 match &self.items[i].item {
1898 WidgetItem::Property { args, .. } if properties.contains(&args.id()) => match self.items.swap_remove(i) {
1899 WidgetItemPositioned {
1900 position,
1901 item: WidgetItem::Property { importance, args, .. },
1902 ..
1903 } => {
1904 out.push_property_positioned(importance, position, args);
1905 found += 1;
1906 }
1907 _ => unreachable!(),
1908 },
1909 _ => {
1910 i += 1;
1911 continue;
1912 }
1913 }
1914 }
1915
1916 i = 0;
1917 while i < self.whens.len() {
1918 let mut ai = 0;
1920 let mut moved_assigns = vec![];
1921 while ai < self.whens[i].when.assigns.len() {
1922 if properties.contains(&self.whens[i].when.assigns[ai].id()) {
1923 let args = self.whens[i].when.assigns.remove(ai);
1924 moved_assigns.push(args);
1925 } else {
1926 ai += 1;
1927 }
1928 }
1929
1930 if !moved_assigns.is_empty() {
1931 let out_imp;
1932 let out_when;
1933 if self.whens[i].when.assigns.is_empty() {
1934 let WhenItemPositioned { importance, mut when, .. } = self.whens.remove(i);
1936 when.assigns = moved_assigns;
1937
1938 out_imp = importance;
1939 out_when = when;
1940 } else {
1941 let WhenItemPositioned { importance, when, .. } = &self.whens[i];
1943 out_imp = *importance;
1944 out_when = WhenInfo {
1945 inputs: when.inputs.clone(),
1946 state: when.state.clone(),
1947 assigns: moved_assigns,
1948 build_action_data: when.build_action_data.clone(),
1949 expr: when.expr,
1950 location: when.location,
1951 };
1952
1953 i += 1;
1954 };
1955
1956 for input in out_when.inputs.iter() {
1958 if let Some(i) = self.property_index(input.property) {
1959 match &self.items[i] {
1960 WidgetItemPositioned {
1961 position,
1962 item: WidgetItem::Property { importance, args, .. },
1963 ..
1964 } => {
1965 out.push_property_positioned(*importance, *position, args.clone());
1966 }
1967 _ => unreachable!(),
1968 }
1969 }
1970 }
1971
1972 out.push_when(out_imp, out_when);
1973 } else {
1974 i += 1;
1975 }
1976 }
1977
1978 for id in properties {
1980 if let Some(imp) = self.unset.remove(&id) {
1981 out.push_unset(imp, id);
1982 }
1983 }
1984 }
1985
1986 pub fn build(self) -> BoxedUiNode {
1992 if let Some(custom) = self.custom_build.clone() {
1993 match custom.try_lock() {
1994 Some(mut c) => c(self),
1995 None => self.default_build(),
1996 }
1997 } else {
1998 self.default_build()
1999 }
2000 }
2001
2002 pub fn default_build(self) -> BoxedUiNode {
2006 #[cfg(feature = "inspector")]
2007 let builder = self.clone();
2008
2009 let mut building = WidgetBuilding {
2010 #[cfg(feature = "inspector")]
2011 builder: Some(builder),
2012 #[cfg(feature = "trace_widget")]
2013 trace_widget: true,
2014 #[cfg(feature = "trace_wgt_item")]
2015 trace_wgt_item: true,
2016
2017 widget_type: self.widget_type,
2018 p: self.p,
2019 child: None,
2020 };
2021
2022 let mut p_build_actions = self.p_build_actions.into_iter().collect();
2023
2024 let mut when_init_context_handle = None;
2025
2026 if !self.whens.is_empty() {
2027 let handle = ContextInitHandle::new();
2028 building.build_whens(self.whens, handle.downgrade(), &mut p_build_actions);
2029 when_init_context_handle = Some(handle);
2030 }
2031
2032 if !p_build_actions.is_empty() {
2033 building.build_p_actions(p_build_actions);
2034 }
2035
2036 for action in self.build_actions {
2037 (action.lock())(&mut building);
2038 }
2039
2040 building.build(when_init_context_handle)
2041 }
2042}
2043impl ops::Deref for WidgetBuilder {
2044 type Target = WidgetBuilderProperties;
2045
2046 fn deref(&self) -> &Self::Target {
2047 &self.p
2048 }
2049}
2050impl ops::DerefMut for WidgetBuilder {
2051 fn deref_mut(&mut self) -> &mut Self::Target {
2052 &mut self.p
2053 }
2054}
2055
2056pub struct WidgetBuilding {
2064 #[cfg(feature = "inspector")]
2065 builder: Option<WidgetBuilder>,
2066 #[cfg(feature = "trace_widget")]
2067 trace_widget: bool,
2068 #[cfg(feature = "trace_wgt_item")]
2069 trace_wgt_item: bool,
2070
2071 widget_type: WidgetType,
2072 p: WidgetBuilderProperties,
2073 child: Option<BoxedUiNode>,
2074}
2075impl WidgetBuilding {
2076 pub fn widget_type(&self) -> WidgetType {
2078 self.widget_type
2079 }
2080
2081 pub fn has_child(&self) -> bool {
2085 self.child.is_some()
2086 }
2087
2088 pub fn set_child(&mut self, node: impl UiNode) {
2090 self.child = Some(node.boxed());
2091 }
2092
2093 #[cfg(feature = "inspector")]
2097 pub fn disable_inspector(&mut self) {
2098 self.builder = None;
2099 }
2100
2101 #[cfg(feature = "trace_widget")]
2105 pub fn disable_trace_widget(&mut self) {
2106 self.trace_widget = false;
2107 }
2108
2109 #[cfg(feature = "trace_wgt_item")]
2113 pub fn disable_trace_wgt_item(&mut self) {
2114 self.trace_wgt_item = false;
2115 }
2116
2117 pub fn push_intrinsic<I: UiNode>(
2121 &mut self,
2122 group: NestGroup,
2123 name: &'static str,
2124 intrinsic: impl FnOnce(BoxedUiNode) -> I + Send + Sync + 'static,
2125 ) {
2126 self.push_intrinsic_positioned(NestPosition::intrinsic(group), name, intrinsic)
2127 }
2128
2129 pub fn push_intrinsic_positioned<I: UiNode>(
2133 &mut self,
2134 position: NestPosition,
2135 name: &'static str,
2136 intrinsic: impl FnOnce(BoxedUiNode) -> I + Send + Sync + 'static,
2137 ) {
2138 self.items.push(WidgetItemPositioned {
2139 position,
2140 insert_idx: u32::MAX,
2141 item: WidgetItem::Intrinsic {
2142 name,
2143 new: Box::new(move |n| intrinsic(n).boxed()),
2144 },
2145 });
2146 }
2147
2148 pub fn remove_property(&mut self, property_id: PropertyId) -> Option<BuilderProperty> {
2152 if let Some(i) = self.property_index(property_id) {
2153 match self.items.swap_remove(i) {
2154 WidgetItemPositioned {
2155 position,
2156 item:
2157 WidgetItem::Property {
2158 importance,
2159 args,
2160 captured,
2161 },
2162 ..
2163 } => Some(BuilderProperty {
2164 importance,
2165 position,
2166 args,
2167 captured,
2168 }),
2169 _ => unreachable!(),
2170 }
2171 } else {
2172 None
2173 }
2174 }
2175
2176 pub fn capture_property(&mut self, property_id: PropertyId) -> Option<BuilderPropertyRef> {
2181 self.capture_property_impl(property_id)
2182 }
2183
2184 pub fn capture_var<T>(&mut self, property_id: PropertyId) -> Option<BoxedVar<T>>
2186 where
2187 T: VarValue,
2188 {
2189 let p = self.capture_property(property_id)?;
2190 let var = p.args.downcast_var::<T>(0).clone();
2191 Some(var)
2192 }
2193
2194 pub fn capture_var_or_else<T, F>(&mut self, property_id: PropertyId, or_else: impl FnOnce() -> F) -> BoxedVar<T>
2196 where
2197 T: VarValue,
2198 F: IntoVar<T>,
2199 {
2200 match self.capture_var::<T>(property_id) {
2201 Some(var) => var,
2202 None => or_else().into_var().boxed(),
2203 }
2204 }
2205
2206 pub fn capture_var_or_default<T>(&mut self, property_id: PropertyId) -> BoxedVar<T>
2208 where
2209 T: VarValue + Default,
2210 {
2211 self.capture_var_or_else(property_id, T::default)
2212 }
2213
2214 pub fn capture_ui_node(&mut self, property_id: PropertyId) -> Option<BoxedUiNode> {
2216 let p = self.capture_property(property_id)?;
2217 let node = p.args.ui_node(0).take_on_init().boxed();
2218 Some(node)
2219 }
2220
2221 pub fn capture_ui_node_or_else<F>(&mut self, property_id: PropertyId, or_else: impl FnOnce() -> F) -> BoxedUiNode
2223 where
2224 F: UiNode,
2225 {
2226 match self.capture_ui_node(property_id) {
2227 Some(u) => u,
2228 None => or_else().boxed(),
2229 }
2230 }
2231
2232 pub fn capture_ui_node_list(&mut self, property_id: PropertyId) -> Option<BoxedUiNodeList> {
2234 let p = self.capture_property(property_id)?;
2235 let list = p.args.ui_node_list(0).take_on_init().boxed();
2236 Some(list)
2237 }
2238
2239 pub fn capture_ui_node_list_or_else<F>(&mut self, property_id: PropertyId, or_else: impl FnOnce() -> F) -> BoxedUiNodeList
2241 where
2242 F: UiNodeList,
2243 {
2244 match self.capture_ui_node_list(property_id) {
2245 Some(u) => u,
2246 None => or_else().boxed(),
2247 }
2248 }
2249
2250 pub fn capture_ui_node_list_or_empty(&mut self, property_id: PropertyId) -> BoxedUiNodeList {
2252 self.capture_ui_node_list_or_else(property_id, Vec::<BoxedUiNode>::new)
2253 }
2254
2255 pub fn capture_widget_handler<A: Clone + 'static>(&mut self, property_id: PropertyId) -> Option<ArcWidgetHandler<A>> {
2257 let p = self.capture_property(property_id)?;
2258 let handler = p.args.downcast_handler::<A>(0).clone();
2259 Some(handler)
2260 }
2261
2262 fn build_whens(
2263 &mut self,
2264 mut whens: Vec<WhenItemPositioned>,
2265 when_init_context_id: WeakContextInitHandle,
2266 build_actions: &mut PropertyBuildActionsVec,
2267 ) {
2268 whens.sort_unstable_by_key(|w| w.sort_key());
2269
2270 struct Input<'a> {
2271 input: &'a WhenInput,
2272 item_idx: usize,
2273 }
2274 let mut inputs = vec![];
2275
2276 struct Assign {
2277 item_idx: usize,
2278 builder: Vec<Box<dyn Any>>,
2279 when_count: usize,
2280 actions_data: HashMap<&'static str, (Vec<Option<WhenBuildActionData>>, Option<WhenBuildDefaultAction>)>,
2283 }
2284 let mut assigns = IdMap::default();
2285
2286 'when: for WhenItemPositioned { when, .. } in whens.iter().rev() {
2288 let valid_inputs = inputs.len();
2290 let valid_items = self.p.items.len();
2291 for input in when.inputs.iter() {
2292 if let Some(i) = self.property_index(input.property) {
2293 inputs.push(Input { input, item_idx: i })
2294 } else if let Some(default) = input.property_default {
2295 let args = default();
2296 self.p.items.push(WidgetItemPositioned {
2297 position: NestPosition::property(args.property().group),
2298 insert_idx: u32::MAX,
2299 item: WidgetItem::Property {
2300 importance: Importance::WIDGET,
2301 args,
2302 captured: false,
2303 },
2304 });
2305 inputs.push(Input {
2306 input,
2307 item_idx: self.p.items.len() - 1,
2308 });
2309 } else {
2310 inputs.truncate(valid_inputs);
2311 self.p.items.truncate(valid_items);
2312 continue 'when;
2313 }
2314 }
2315
2316 let mut any_assign = false;
2317 'assign: for assign in when.assigns.iter() {
2319 let id = assign.id();
2320 let assign_info;
2321 let i;
2322 if let Some(idx) = self.property_index(id) {
2323 assign_info = assign.property();
2324 i = idx;
2325 } else if let Some(default) = assign.property().default {
2326 let args = default();
2327 assign_info = args.property();
2328 i = self.p.items.len();
2329 self.p.items.push(WidgetItemPositioned {
2330 position: NestPosition::property(args.property().group),
2331 insert_idx: u32::MAX,
2332 item: WidgetItem::Property {
2333 importance: Importance::WIDGET,
2334 args,
2335 captured: false,
2336 },
2337 });
2338 } else {
2339 tracing::warn!(
2340 "property `{}` ignored, it is only set in `when` block and has no default value",
2341 assign.property().name
2342 );
2343 continue;
2344 }
2345
2346 any_assign = true;
2347
2348 let default_args = match &self.items[i].item {
2349 WidgetItem::Property { args, .. } => args,
2350 WidgetItem::Intrinsic { .. } => unreachable!(),
2351 };
2352 let info = default_args.property();
2353
2354 for (default_info, assign_info) in info.inputs.iter().zip(assign_info.inputs.iter()) {
2355 if default_info.ty != assign_info.ty {
2356 continue 'assign;
2358 }
2359 }
2360
2361 let entry = match assigns.entry(id) {
2362 IdEntry::Occupied(e) => e.into_mut(),
2363 IdEntry::Vacant(e) => e.insert(Assign {
2364 item_idx: i,
2365 builder: info
2366 .inputs
2367 .iter()
2368 .enumerate()
2369 .map(|(i, input)| match input.kind {
2370 InputKind::Var => Box::new(AnyWhenVarBuilder::new_any(default_args.var(i).clone_any())) as _,
2371 InputKind::UiNode => Box::new(WhenUiNodeBuilder::new(default_args.ui_node(i).take_on_init())) as _,
2372 InputKind::UiNodeList => {
2373 Box::new(WhenUiNodeListBuilder::new(default_args.ui_node_list(i).take_on_init())) as _
2374 }
2375 InputKind::WidgetHandler => {
2376 Box::new(AnyWhenArcWidgetHandlerBuilder::new(default_args.widget_handler(i).clone_boxed())) as _
2377 }
2378 InputKind::Value => panic!("can only assign vars in when blocks"),
2379 })
2380 .collect(),
2381 when_count: 0,
2382 actions_data: Default::default(),
2383 }),
2384 };
2385 entry.when_count += 1;
2386
2387 for (i, (input, entry)) in info.inputs.iter().zip(entry.builder.iter_mut()).enumerate() {
2388 match input.kind {
2389 InputKind::Var => {
2390 let entry = entry.downcast_mut::<AnyWhenVarBuilder>().unwrap();
2391 let value = assign.var(i).clone_any();
2392 entry.push_any(when.state.clone(), value);
2393 }
2394 InputKind::UiNode => {
2395 let entry = entry.downcast_mut::<WhenUiNodeBuilder>().unwrap();
2396 let node = assign.ui_node(i).take_on_init();
2397 entry.push(when.state.clone(), node);
2398 }
2399 InputKind::UiNodeList => {
2400 let entry = entry.downcast_mut::<WhenUiNodeListBuilder>().unwrap();
2401 let list = assign.ui_node_list(i).take_on_init();
2402 entry.push(when.state.clone(), list);
2403 }
2404 InputKind::WidgetHandler => {
2405 let entry = entry.downcast_mut::<AnyWhenArcWidgetHandlerBuilder>().unwrap();
2406 let handler = assign.widget_handler(i).clone_boxed();
2407 entry.push(when.state.clone(), handler);
2408 }
2409 InputKind::Value => panic!("cannot assign `Value` in when blocks"),
2410 }
2411 }
2412
2413 for ((property_id, action_key), action) in &when.build_action_data {
2414 if *property_id == id {
2415 match entry.actions_data.entry(*action_key) {
2416 hash_map::Entry::Occupied(mut e) => {
2417 let e = e.get_mut();
2418 for _ in e.0.len()..(entry.when_count - 1) {
2419 e.0.push(None);
2420 }
2421 e.0.push(Some(action.data.clone()));
2422 if action.default_action.is_some() && e.1.is_none() {
2423 e.1.clone_from(&action.default_action);
2424 }
2425 }
2426 hash_map::Entry::Vacant(e) => {
2427 let mut a = Vec::with_capacity(entry.when_count);
2428 for _ in 0..(entry.when_count - 1) {
2429 a.push(None);
2430 }
2431 a.push(Some(action.data.clone()));
2432 e.insert((a, action.default_action.clone()));
2433 }
2434 }
2435 }
2436 }
2437 }
2438
2439 if !any_assign {
2440 inputs.truncate(valid_inputs);
2441 self.p.items.truncate(valid_items);
2442 }
2443 }
2444
2445 for Input { input, item_idx } in inputs {
2446 let args = match &self.items[item_idx].item {
2447 WidgetItem::Property { args, .. } => args,
2448 WidgetItem::Intrinsic { .. } => unreachable!(),
2449 };
2450 let info = args.property();
2451
2452 let member_i = match input.member {
2453 WhenInputMember::Named(name) => info.input_idx(name).expect("when ref named input not found"),
2454 WhenInputMember::Index(i) => i,
2455 };
2456
2457 let actual = match info.inputs[member_i].kind {
2458 InputKind::Var => args.var(member_i).clone_any(),
2459 InputKind::Value => args.value(member_i).clone_boxed_var(),
2460 _ => panic!("can only ref var or values in when expr"),
2461 };
2462 input.var.set(when_init_context_id.clone(), actual);
2463 }
2464
2465 for (
2466 _,
2467 Assign {
2468 item_idx,
2469 builder,
2470 when_count,
2471 mut actions_data,
2472 },
2473 ) in assigns
2474 {
2475 let args = match &mut self.items[item_idx].item {
2476 WidgetItem::Property { args, .. } => args,
2477 WidgetItem::Intrinsic { .. } => unreachable!(),
2478 };
2479
2480 let mut actions = vec![];
2481 let mut b_actions_data = vec![];
2482 if !build_actions.is_empty() {
2483 let p_id = args.id();
2484 while let Some(i) = build_actions.iter().position(|((id, _), _)| *id == p_id) {
2485 let ((_, action_key), (_, a)) = build_actions.swap_remove(i);
2486 actions.push(a);
2487
2488 if let Some(data) = actions_data.remove(action_key) {
2489 let mut data = data.clone();
2490 for _ in data.0.len()..when_count {
2491 data.0.push(None);
2492 }
2493 b_actions_data.push(data.0);
2494 }
2495 }
2496 }
2497
2498 for (_, (mut data, default)) in actions_data {
2499 if let Some(default) = default {
2500 let action = default();
2501 for _ in data.len()..when_count {
2502 data.push(None);
2503 }
2504
2505 actions.push(action);
2506 b_actions_data.push(data);
2507 }
2508 }
2509
2510 *args = (args.property().new)(PropertyNewArgs {
2511 args: builder,
2512 build_actions: actions,
2513 build_actions_when_data: b_actions_data,
2514 });
2515 }
2516 }
2517
2518 fn build_p_actions(&mut self, mut build_actions: PropertyBuildActionsVec) {
2519 while !build_actions.is_empty() {
2520 let ((p_id, _), (_, a)) = build_actions.swap_remove(0);
2521 let mut actions = vec![a];
2522
2523 while let Some(i) = build_actions.iter().position(|((id, _), _)| *id == p_id) {
2524 let (_, (_, a)) = build_actions.swap_remove(i);
2525 actions.push(a);
2526 }
2527
2528 if let Some(i) = self.property_index(p_id) {
2529 match &mut self.items[i].item {
2530 WidgetItem::Property { args, .. } => *args = args.new_build(actions, vec![]),
2531 WidgetItem::Intrinsic { .. } => unreachable!(),
2532 }
2533 }
2534 }
2535 }
2536
2537 fn build(mut self, when_init_context_handle: Option<ContextInitHandle>) -> BoxedUiNode {
2538 self.items.sort_unstable_by_key(|b| b.sort_key());
2540
2541 #[cfg(feature = "inspector")]
2542 let mut inspector_items = Vec::with_capacity(self.p.items.len());
2543
2544 let mut node = self.child.take().unwrap_or_else(|| FillUiNode.boxed());
2545 for WidgetItemPositioned { position, item, .. } in self.p.items.into_iter().rev() {
2546 match item {
2547 WidgetItem::Property { args, captured, .. } => {
2548 if !captured {
2549 #[cfg(debug_assertions)]
2550 {
2551 let p = args.property();
2552 if p.capture {
2553 tracing::error!(
2554 "capture only property `{}` is not captured in `{}!`, it will have no effect",
2555 p.name,
2556 self.widget_type.name()
2557 );
2558 }
2559 }
2560
2561 node = args.instantiate(node);
2562
2563 #[cfg(feature = "trace_wgt_item")]
2564 if self.trace_wgt_item {
2565 let name = args.property().name;
2566 node = node.trace(move |mtd| crate::update::UpdatesTrace::property_span(name, mtd.mtd_name()));
2567 }
2568 }
2569
2570 #[cfg(feature = "inspector")]
2571 {
2572 if args.property().inputs.iter().any(|i| matches!(i.kind, InputKind::Var)) {
2573 node = crate::widget::inspector::actualize_var_info(node, args.id()).boxed();
2574 }
2575
2576 inspector_items.push(crate::widget::inspector::InstanceItem::Property { args, captured });
2577 }
2578 }
2579 #[allow(unused_variables)] WidgetItem::Intrinsic { new, name } => {
2581 node = new(node);
2582 #[cfg(feature = "trace_wgt_item")]
2583 if self.trace_wgt_item {
2584 node = node.trace(move |mtd| crate::update::UpdatesTrace::intrinsic_span(name, mtd.mtd_name()));
2585 }
2586
2587 #[cfg(feature = "inspector")]
2588 inspector_items.push(crate::widget::inspector::InstanceItem::Intrinsic {
2589 group: position.group,
2590 name,
2591 });
2592
2593 #[cfg(not(feature = "inspector"))]
2594 let _ = position;
2595 }
2596 }
2597 }
2598
2599 #[cfg(feature = "inspector")]
2600 if let Some(builder) = self.builder {
2601 node = crate::widget::inspector::insert_widget_builder_info(
2602 node,
2603 crate::widget::inspector::InspectorInfo {
2604 builder,
2605 items: inspector_items.into_boxed_slice(),
2606 actual_vars: crate::widget::inspector::InspectorActualVars::default(),
2607 },
2608 )
2609 .boxed();
2610 }
2611
2612 #[cfg(feature = "trace_widget")]
2613 if self.trace_widget {
2614 let name = self.widget_type.name();
2615 node = node
2616 .trace(move |op| crate::update::UpdatesTrace::widget_span(crate::widget::WIDGET.id(), name, op.mtd_name()))
2617 .boxed();
2618 }
2619
2620 node = with_new_context_init_id(node).boxed();
2622
2623 if let Some(handle) = when_init_context_handle {
2624 let mut handle = Some(Arc::new(handle));
2626 node = crate::widget::node::match_node(node, move |c, op| {
2627 WHEN_INPUT_CONTEXT_INIT_ID.with_context(&mut handle, || c.op(op));
2628 })
2629 .boxed();
2630 }
2631
2632 node
2633 }
2634}
2635impl ops::Deref for WidgetBuilding {
2636 type Target = WidgetBuilderProperties;
2637
2638 fn deref(&self) -> &Self::Target {
2639 &self.p
2640 }
2641}
2642impl ops::DerefMut for WidgetBuilding {
2643 fn deref_mut(&mut self) -> &mut Self::Target {
2644 &mut self.p
2645 }
2646}
2647
2648#[derive(Debug)]
2650pub struct BuilderProperty {
2651 pub importance: Importance,
2653 pub position: NestPosition,
2655 pub args: Box<dyn PropertyArgs>,
2657 pub captured: bool,
2659}
2660
2661#[derive(Debug)]
2663pub struct BuilderPropertyRef<'a> {
2664 pub importance: Importance,
2666 pub position: NestPosition,
2668 pub args: &'a dyn PropertyArgs,
2670 pub captured: bool,
2674}
2675
2676#[derive(Debug)]
2678pub struct BuilderPropertyMut<'a> {
2679 pub importance: &'a mut Importance,
2681 pub position: &'a mut NestPosition,
2683 pub args: &'a mut Box<dyn PropertyArgs>,
2685 pub captured: &'a mut bool,
2689}
2690
2691pub struct WidgetBuilderProperties {
2693 items: Vec<WidgetItemPositioned>,
2694}
2695impl WidgetBuilderProperties {
2696 pub fn property(&self, property_id: PropertyId) -> Option<BuilderPropertyRef> {
2698 match self.property_index(property_id) {
2699 Some(i) => match &self.items[i].item {
2700 WidgetItem::Property {
2701 importance,
2702 args,
2703 captured,
2704 } => Some(BuilderPropertyRef {
2705 importance: *importance,
2706 position: self.items[i].position,
2707 args: &**args,
2708 captured: *captured,
2709 }),
2710 WidgetItem::Intrinsic { .. } => unreachable!(),
2711 },
2712 None => None,
2713 }
2714 }
2715
2716 pub fn property_mut(&mut self, property_id: PropertyId) -> Option<BuilderPropertyMut> {
2718 match self.property_index(property_id) {
2719 Some(i) => match &mut self.items[i] {
2720 WidgetItemPositioned {
2721 position,
2722 item:
2723 WidgetItem::Property {
2724 importance,
2725 args,
2726 captured,
2727 },
2728 ..
2729 } => Some(BuilderPropertyMut {
2730 importance,
2731 position,
2732 args,
2733 captured,
2734 }),
2735 _ => unreachable!(),
2736 },
2737 None => None,
2738 }
2739 }
2740
2741 pub fn properties(&self) -> impl Iterator<Item = BuilderPropertyRef> {
2745 self.items.iter().filter_map(|it| match &it.item {
2746 WidgetItem::Intrinsic { .. } => None,
2747 WidgetItem::Property {
2748 importance,
2749 args,
2750 captured,
2751 } => Some(BuilderPropertyRef {
2752 importance: *importance,
2753 position: it.position,
2754 args: &**args,
2755 captured: *captured,
2756 }),
2757 })
2758 }
2759
2760 pub fn properties_mut(&mut self) -> impl Iterator<Item = BuilderPropertyMut> {
2762 self.items.iter_mut().filter_map(|it| match &mut it.item {
2763 WidgetItem::Intrinsic { .. } => None,
2764 WidgetItem::Property {
2765 importance,
2766 args,
2767 captured,
2768 } => Some(BuilderPropertyMut {
2769 importance,
2770 position: &mut it.position,
2771 args,
2772 captured,
2773 }),
2774 })
2775 }
2776
2777 pub fn capture_value<T>(&mut self, property_id: PropertyId) -> Option<T>
2785 where
2786 T: VarValue,
2787 {
2788 let p = self.capture_property_impl(property_id)?;
2789 let value = p.args.downcast_value::<T>(0).clone();
2790 Some(value)
2791 }
2792
2793 pub fn capture_value_or_else<T>(&mut self, property_id: PropertyId, or_else: impl FnOnce() -> T) -> T
2795 where
2796 T: VarValue,
2797 {
2798 match self.capture_value(property_id) {
2799 Some(v) => v,
2800 None => or_else(),
2801 }
2802 }
2803
2804 pub fn capture_value_or_default<T>(&mut self, property_id: PropertyId) -> T
2806 where
2807 T: VarValue + Default,
2808 {
2809 self.capture_value_or_else(property_id, T::default)
2810 }
2811
2812 fn capture_property_impl(&mut self, property_id: PropertyId) -> Option<BuilderPropertyRef> {
2813 if let Some(i) = self.property_index(property_id) {
2814 match &mut self.items[i] {
2815 WidgetItemPositioned {
2816 position,
2817 item:
2818 WidgetItem::Property {
2819 importance,
2820 args,
2821 captured,
2822 },
2823 ..
2824 } => {
2825 *captured = true;
2826 Some(BuilderPropertyRef {
2827 importance: *importance,
2828 position: *position,
2829 args: &**args,
2830 captured: *captured,
2831 })
2832 }
2833 _ => unreachable!(),
2834 }
2835 } else {
2836 None
2837 }
2838 }
2839
2840 fn property_index(&self, property_id: PropertyId) -> Option<usize> {
2841 self.items.iter().position(|it| match &it.item {
2842 WidgetItem::Property { args, .. } => args.id() == property_id,
2843 WidgetItem::Intrinsic { .. } => false,
2844 })
2845 }
2846}
2847
2848pub trait AnyPropertyBuildAction: crate::private::Sealed + Any + Send + Sync {
2850 fn as_any(&self) -> &dyn Any;
2852
2853 fn clone_boxed(&self) -> Box<dyn AnyPropertyBuildAction>;
2855}
2856
2857pub struct PropertyBuildActionArgs<'a, I: Any + Send> {
2859 pub input: I,
2861 pub when_conditions_data: &'a [Option<WhenBuildActionData>],
2865}
2866
2867pub struct PropertyBuildAction<I: Any + Send>(Arc<Mutex<dyn FnMut(PropertyBuildActionArgs<I>) -> I + Send>>);
2887impl<I: Any + Send> crate::private::Sealed for PropertyBuildAction<I> {}
2888impl<I: Any + Send> Clone for PropertyBuildAction<I> {
2889 fn clone(&self) -> Self {
2890 Self(self.0.clone())
2891 }
2892}
2893impl<I: Any + Send> AnyPropertyBuildAction for PropertyBuildAction<I> {
2894 fn clone_boxed(&self) -> Box<dyn AnyPropertyBuildAction> {
2895 Box::new(self.clone())
2896 }
2897
2898 fn as_any(&self) -> &dyn Any {
2899 self
2900 }
2901}
2902impl<I: Any + Send> PropertyBuildAction<I> {
2903 pub fn new(build: impl FnMut(PropertyBuildActionArgs<I>) -> I + Send + 'static) -> Self {
2905 Self(Arc::new(Mutex::new(build)))
2906 }
2907
2908 pub fn no_op() -> Self {
2910 Self::new(|i| i.input)
2911 }
2912
2913 pub fn build(&self, args: PropertyBuildActionArgs<I>) -> I {
2915 (self.0.lock())(args)
2916 }
2917}
2918impl Clone for Box<dyn AnyPropertyBuildAction> {
2919 fn clone(&self) -> Self {
2920 self.clone_boxed()
2921 }
2922}
2923
2924pub struct PropertyInputTypes<Tuple>(std::marker::PhantomData<Tuple>);
2985impl<Tuple> PropertyInputTypes<Tuple> {
2986 pub const fn unit() -> Self {
2988 Self(std::marker::PhantomData)
2989 }
2990}
2991impl<Tuple> Clone for PropertyInputTypes<Tuple> {
2992 fn clone(&self) -> Self {
2993 *self
2994 }
2995}
2996impl<Tuple> Copy for PropertyInputTypes<Tuple> {}
2997unsafe impl<Tuple> Send for PropertyInputTypes<Tuple> {}
2999unsafe impl<Tuple> Sync for PropertyInputTypes<Tuple> {}