1use crate::{
4 handler::{ArcHandler, Handler, HandlerExt},
5 widget::node::IntoUiNode,
6};
7use std::{
8 any::{Any, TypeId},
9 collections::{HashMap, hash_map},
10 fmt, ops,
11 sync::Arc,
12};
13
14#[doc(hidden)]
15pub use zng_var::{var_getter, var_state};
16
17#[macro_export]
21macro_rules! source_location {
22 () => {
23 $crate::widget::builder::SourceLocation::new(std::file!(), std::line!(), std::column!())
24 };
25}
26#[doc(inline)]
27pub use crate::source_location;
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
35#[non_exhaustive]
36pub struct SourceLocation {
37 pub file: &'static str,
39 pub line: u32,
41 pub column: u32,
43}
44
45impl SourceLocation {
46 #[doc(hidden)]
47 pub fn new(file: &'static str, line: u32, column: u32) -> Self {
48 Self { file, line, column }
49 }
50}
51impl fmt::Display for SourceLocation {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "{}:{}:{}", self.file, self.line, self.column)
54 }
55}
56
57#[doc(hidden)]
58pub struct WgtInfo;
59impl WidgetExt for WgtInfo {
60 fn ext_property__(&mut self, _: Box<dyn PropertyArgs>) {
61 panic!("WgtInfo is for extracting info only")
62 }
63
64 fn ext_property_unset__(&mut self, _: PropertyId) {
65 panic!("WgtInfo is for extracting info only")
66 }
67}
68
69#[macro_export]
102macro_rules! property_id {
103 ($($tt:tt)*) => {
104 $crate::widget::property_meta!($($tt)*).id()
105 }
106}
107#[doc(inline)]
108pub use crate::property_id;
109
110#[macro_export]
137macro_rules! property_info {
138 ($($property:ident)::+ <$($generics:ty),*>) => {
139 $crate::widget::property_meta!($($property)::+).info::<$($generics),*>()
140 };
141 ($($tt:tt)*) => {
142 $crate::widget::property_meta!($($tt)*).info()
143 }
144}
145#[doc(inline)]
146pub use crate::property_info;
147
148#[macro_export]
157macro_rules! property_input_types {
158 ($($tt:tt)*) => {
159 $crate::widget::property_meta!($($tt)*).input_types()
160 }
161}
162#[doc(inline)]
163pub use crate::property_input_types;
164
165#[macro_export]
183macro_rules! property_args {
184 ($($property:ident)::+ = $($value:tt)*) => {
185 {
186 $crate::widget::builder::PropertyArgsGetter! {
187 $($property)::+ = $($value)*
188 }
189 }
190 };
191 ($($property:ident)::+ ::<$($generics:ty),*> = $($value:tt)*) => {
192 {
193 $crate::widget::builder::PropertyArgsGetter! {
194 $($property)::+ ::<$($generics),*> = $($value)*
195 }
196 }
197 };
198 ($property:ident $(;)?) => {
199 {
200 $crate::widget::builder::PropertyArgsGetter! {
201 $property
202 }
203 }
204 }
205}
206#[doc(inline)]
207pub use crate::property_args;
208
209#[macro_export]
211macro_rules! widget_type {
212 ($($widget:ident)::+) => {
213 $($widget)::+::widget_type()
214 };
215}
216#[doc(inline)]
217pub use widget_type;
218use zng_app_context::context_local;
219use zng_app_proc_macros::widget;
220use zng_task::parking_lot::Mutex;
221use zng_txt::{Txt, formatx};
222use zng_unique_id::{IdEntry, IdMap, IdSet, unique_id_32};
223use zng_var::{
224 AnyVar, AnyVarValue, AnyWhenVarBuilder, ContextInitHandle, IntoValue, IntoVar, Var, VarValue, WeakContextInitHandle, any_const_var,
225 const_var, contextual_var, impl_from_and_into_var,
226};
227
228use super::{
229 base::{WidgetBase, WidgetExt},
230 node::{ArcNode, FillUiNode, UiNode, WhenUiNodeBuilder, with_new_context_init_id},
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.into_iter().min_by_key(|i| (self.0 as i32 - i.0 as i32).abs()).unwrap();
451 let diff = self.0 as i32 - closest.0 as i32;
452
453 let name = closest.exact_name();
454 debug_assert!(!name.is_empty());
455
456 formatx!("{closest}{diff:+}")
457 } else {
458 Txt::from_static(name)
459 }
460 }
461}
462impl fmt::Debug for NestGroup {
463 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
464 if f.alternate() {
465 write!(f, "NestGroup::")?;
466 }
467 write!(f, "{}", self.name())
468 }
469}
470impl fmt::Display for NestGroup {
471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472 write!(f, "{}", self.name())
473 }
474}
475impl ops::Add<i16> for NestGroup {
476 type Output = Self;
477
478 fn add(self, rhs: i16) -> Self::Output {
479 let r = (self.0 as i32) + rhs as i32;
480
481 Self(r.clamp(0, u16::MAX as i32) as u16)
482 }
483}
484impl ops::Sub<i16> for NestGroup {
485 type Output = Self;
486
487 fn sub(self, rhs: i16) -> Self::Output {
488 let r = (self.0 as i32) - rhs as i32;
489
490 Self(r.clamp(0, u16::MAX as i32) as u16)
491 }
492}
493impl ops::AddAssign<i16> for NestGroup {
494 fn add_assign(&mut self, rhs: i16) {
495 *self = *self + rhs;
496 }
497}
498impl ops::SubAssign<i16> for NestGroup {
499 fn sub_assign(&mut self, rhs: i16) {
500 *self = *self - rhs;
501 }
502}
503#[test]
504fn nest_group_spacing() {
505 let mut expected = NestGroup::NEXT_GROUP;
506 for g in &NestGroup::ITEMS[1..NestGroup::ITEMS.len() - 1] {
507 assert_eq!(expected, g.0);
508 expected += NestGroup::NEXT_GROUP;
509 }
510 assert_eq!(expected, (u16::MAX / 10) * 10); }
512#[derive(serde::Deserialize)]
513#[serde(untagged)]
514enum NestGroupSerde<'s> {
515 Named(&'s str),
516 Unnamed(u16),
517}
518impl serde::Serialize for NestGroup {
519 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
520 where
521 S: serde::Serializer,
522 {
523 if serializer.is_human_readable() {
524 self.name().serialize(serializer)
525 } else {
526 self.0.serialize(serializer)
527 }
528 }
529}
530impl<'de> serde::Deserialize<'de> for NestGroup {
531 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
532 where
533 D: serde::Deserializer<'de>,
534 {
535 use serde::de::Error;
536
537 match NestGroupSerde::deserialize(deserializer)? {
538 NestGroupSerde::Named(n) => match n.parse() {
539 Ok(g) => Ok(g),
540 Err(e) => Err(D::Error::custom(e)),
541 },
542 NestGroupSerde::Unnamed(i) => Ok(NestGroup(i)),
543 }
544 }
545}
546impl std::str::FromStr for NestGroup {
547 type Err = String;
548
549 fn from_str(s: &str) -> Result<Self, Self::Err> {
550 let mut name = s;
551 let mut add = 0i16;
552
553 if let Some((n, a)) = s.split_once('+') {
554 add = a.parse().map_err(|e| format!("{e}"))?;
555 name = n;
556 } else if let Some((n, s)) = s.split_once('-') {
557 add = -s.parse().map_err(|e| format!("{e}"))?;
558 name = n;
559 }
560
561 match name {
562 "WIDGET" => Ok(NestGroup::WIDGET + add),
563 "CONTEXT" => Ok(NestGroup::CONTEXT + add),
564 "EVENT" => Ok(NestGroup::EVENT + add),
565 "LAYOUT" => Ok(NestGroup::LAYOUT + add),
566 "SIZE" => Ok(NestGroup::SIZE + add),
567 "BORDER" => Ok(NestGroup::BORDER + add),
568 "FILL" => Ok(NestGroup::FILL + add),
569 "CHILD_CONTEXT" => Ok(NestGroup::CHILD_CONTEXT + add),
570 "CHILD_LAYOUT" => Ok(NestGroup::CHILD_LAYOUT + add),
571 "CHILD" => Ok(NestGroup::CHILD + add),
572 ukn => Err(format!("unknown nest group {ukn:?}")),
573 }
574 }
575}
576
577#[derive(PartialEq, Eq, Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
579pub enum InputKind {
580 Var,
582 Value,
584 UiNode,
586 Handler,
588}
589
590pub trait AnyArcHandler: Any {
592 fn as_any(&self) -> &dyn Any;
594
595 fn into_any(self: Box<Self>) -> Box<dyn Any>;
597
598 fn clone_boxed(&self) -> Box<dyn AnyArcHandler>;
600}
601impl<A: Clone + 'static> AnyArcHandler for ArcHandler<A> {
602 fn clone_boxed(&self) -> Box<dyn AnyArcHandler> {
603 Box::new(self.clone())
604 }
605
606 fn as_any(&self) -> &dyn Any {
607 self
608 }
609
610 fn into_any(self: Box<Self>) -> Box<dyn Any> {
611 self
612 }
613}
614
615pub struct AnyWhenArcHandlerBuilder {
619 default: Box<dyn AnyArcHandler>,
620 conditions: Vec<(Var<bool>, Box<dyn AnyArcHandler>)>,
621}
622impl AnyWhenArcHandlerBuilder {
623 pub fn new(default: Box<dyn AnyArcHandler>) -> Self {
625 Self {
626 default,
627 conditions: vec![],
628 }
629 }
630
631 pub fn push(&mut self, condition: Var<bool>, handler: Box<dyn AnyArcHandler>) {
633 self.conditions.push((condition, handler));
634 }
635
636 pub fn build<A: Clone + 'static>(self) -> ArcHandler<A> {
638 match self.default.into_any().downcast::<ArcHandler<A>>() {
639 Ok(default) => {
640 let mut conditions = Vec::with_capacity(self.conditions.len());
641 for (c, h) in self.conditions {
642 match h.into_any().downcast::<ArcHandler<A>>() {
643 Ok(h) => conditions.push((c, *h)),
644 Err(_) => continue,
645 }
646 }
647 let handler: Handler<A> = Box::new(move |args: &A| {
648 for (c, h) in &conditions {
649 if c.get() {
650 return h.call(args);
651 }
652 }
653 default.call(args)
654 });
655 handler.into_arc()
656 }
657 Err(_) => panic!("unexpected build type in widget handler when builder"),
658 }
659 }
660}
661
662pub type PropertyAttributes = Vec<Vec<Box<dyn AnyPropertyAttribute>>>;
666
667pub type PropertyAttributesWhenData = Vec<Vec<Option<PropertyAttributeWhenData>>>;
671
672#[non_exhaustive]
674pub struct PropertyNewArgs {
675 pub args: Vec<Box<dyn Any>>,
694
695 pub attributes: PropertyAttributes,
714
715 pub attributes_when_data: PropertyAttributesWhenData,
721}
722
723#[derive(Debug, Clone)]
727pub struct PropertyInfo {
728 pub group: NestGroup,
730 pub build_action: bool,
734
735 pub id: PropertyId,
737 pub name: &'static str,
739
740 pub location: SourceLocation,
742
743 pub default: Option<fn() -> Box<dyn PropertyArgs>>,
747
748 pub new: fn(PropertyNewArgs) -> Box<dyn PropertyArgs>,
758
759 pub inputs: Box<[PropertyInput]>,
761
762 #[doc(hidden)] pub _non_exhaustive: (),
764}
765impl PropertyInfo {
766 pub fn input_idx(&self, name: &str) -> Option<usize> {
768 self.inputs.iter().position(|i| i.name == name)
769 }
770}
771
772#[derive(Debug, Clone)]
774pub struct PropertyInput {
775 pub name: &'static str,
777 pub kind: InputKind,
779
780 pub ty: TypeId,
796 pub ty_name: &'static str,
800
801 #[doc(hidden)] pub _non_exhaustive: (),
803}
804impl PropertyInput {
805 pub fn short_ty_name(&self) -> Txt {
809 pretty_type_name::pretty_type_name_str(self.ty_name).into()
810 }
811
812 pub fn actual_ty_name(&self) -> Txt {
814 match self.kind {
815 InputKind::Var => formatx!("Var<{}>", self.short_ty_name()),
816 InputKind::Handler => formatx!("Handler<{}>", self.short_ty_name()),
817 InputKind::Value => self.short_ty_name(),
818 InputKind::UiNode => self.short_ty_name(),
819 }
820 }
821
822 pub fn input_ty_name(&self) -> Txt {
836 match self.kind {
837 InputKind::Var => formatx!("impl IntoVar<{}>", self.short_ty_name()),
838 InputKind::Value => formatx!("impl IntoValue<{}>", self.short_ty_name()),
839 InputKind::UiNode => Txt::from_static("impl IntoUiNode"),
840 InputKind::Handler => formatx!("Handler<{}>", self.short_ty_name()),
841 }
842 }
843}
844
845pub trait PropertyArgs: Send + Sync {
847 fn clone_boxed(&self) -> Box<dyn PropertyArgs>;
849
850 fn property(&self) -> PropertyInfo;
852
853 fn var(&self, i: usize) -> &AnyVar {
855 panic_input(&self.property(), i, InputKind::Var)
856 }
857
858 fn value(&self, i: usize) -> &dyn AnyVarValue {
860 panic_input(&self.property(), i, InputKind::Value)
861 }
862
863 fn ui_node(&self, i: usize) -> &ArcNode {
865 panic_input(&self.property(), i, InputKind::UiNode)
866 }
867
868 fn handler(&self, i: usize) -> &dyn AnyArcHandler {
872 panic_input(&self.property(), i, InputKind::Handler)
873 }
874
875 fn build_action(&self, wgt: &mut WidgetBuilding);
879
880 fn instantiate(&self, child: UiNode) -> UiNode;
884}
885impl dyn PropertyArgs + '_ {
886 pub fn id(&self) -> PropertyId {
888 self.property().id
889 }
890
891 pub fn downcast_value<T>(&self, i: usize) -> &T
897 where
898 T: VarValue,
899 {
900 self.value(i).downcast_ref::<T>().expect("cannot downcast value to type")
901 }
902 pub fn downcast_var<T>(&self, i: usize) -> Var<T>
908 where
909 T: VarValue,
910 {
911 self.var(i)
912 .clone()
913 .downcast::<T>()
914 .unwrap_or_else(|_| panic!("cannot downcast var to type"))
915 }
916
917 pub fn downcast_handler<A>(&self, i: usize) -> &ArcHandler<A>
923 where
924 A: 'static + Clone,
925 {
926 self.handler(i)
927 .as_any()
928 .downcast_ref::<ArcHandler<A>>()
929 .expect("cannot downcast handler to type")
930 }
931
932 pub fn live_debug(&self, i: usize) -> Var<Txt> {
938 let p = self.property();
939 match p.inputs[i].kind {
940 InputKind::Var => self.var(i).map_debug(false),
941 InputKind::Value => const_var(formatx!("{:?}", self.value(i))),
942 InputKind::UiNode => const_var(Txt::from_static("UiNode")),
943 InputKind::Handler => const_var(formatx!("Handler<{}>", p.inputs[i].short_ty_name())),
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()),
954 InputKind::Value => formatx!("{:?}", self.value(i)),
955 InputKind::UiNode => Txt::from_static("UiNode"),
956 InputKind::Handler => formatx!("Handler<{}>", p.inputs[i].short_ty_name()),
957 }
958 }
959
960 pub fn new_build(&self, attributes: PropertyAttributes, attributes_when_data: PropertyAttributesWhenData) -> Box<dyn PropertyArgs> {
964 let p = self.property();
965
966 let mut args: Vec<Box<dyn Any>> = Vec::with_capacity(p.inputs.len());
967 for (i, input) in p.inputs.iter().enumerate() {
968 match input.kind {
969 InputKind::Var => args.push(Box::new(self.var(i).clone())),
970 InputKind::Value => args.push(Box::new(self.value(i).clone_boxed())),
971 InputKind::UiNode => args.push(Box::new(self.ui_node(i).clone())),
972 InputKind::Handler => args.push(self.handler(i).clone_boxed().into_any()),
973 }
974 }
975
976 (p.new)(PropertyNewArgs {
977 args,
978 attributes,
979 attributes_when_data,
980 })
981 }
982}
983
984#[doc(hidden)]
985pub fn panic_input(info: &PropertyInfo, i: usize, kind: InputKind) -> ! {
986 if i > info.inputs.len() {
987 panic!("index out of bounds, the input len is {}, but the index is {i}", info.inputs.len())
988 } else if info.inputs[i].kind != kind {
989 panic!(
990 "invalid input request `{:?}`, but `{}` is `{:?}`",
991 kind, info.inputs[i].name, info.inputs[i].kind
992 )
993 } else {
994 panic!("invalid input `{}`", info.inputs[i].name)
995 }
996}
997
998#[doc(hidden)]
999pub fn var_to_args<T: VarValue>(var: impl IntoVar<T>) -> Var<T> {
1000 var.into_var()
1001}
1002
1003#[doc(hidden)]
1004pub fn value_to_args<T: VarValue>(value: impl IntoValue<T>) -> T {
1005 value.into()
1006}
1007
1008#[doc(hidden)]
1009pub fn ui_node_to_args(node: impl IntoUiNode) -> ArcNode {
1010 ArcNode::new(node)
1011}
1012
1013#[doc(hidden)]
1014pub fn handler_to_args<A: Clone + 'static>(handler: Handler<A>) -> ArcHandler<A> {
1015 handler.into_arc()
1016}
1017
1018#[doc(hidden)]
1019pub fn iter_input_attributes<'a>(
1020 attributes: &'a PropertyAttributes,
1021 data: &'a PropertyAttributesWhenData,
1022 index: usize,
1023) -> impl Iterator<Item = (&'a dyn AnyPropertyAttribute, &'a [Option<PropertyAttributeWhenData>])> {
1024 let mut attributes = attributes.iter();
1025 let mut data = data.iter();
1026
1027 std::iter::from_fn(move || {
1028 let action = &*attributes.next()?[index];
1029 let data = if let Some(data) = data.next() { &data[..] } else { &[] };
1030
1031 Some((action, data))
1032 })
1033}
1034
1035fn apply_attributes<'a, I: Any + Send>(
1036 mut item: I,
1037 mut attributes: impl Iterator<Item = (&'a dyn AnyPropertyAttribute, &'a [Option<PropertyAttributeWhenData>])>,
1038) -> I {
1039 if let Some((attribute, data)) = attributes.next() {
1040 let attribute = attribute
1041 .as_any()
1042 .downcast_ref::<PropertyAttribute<I>>()
1043 .expect("property attribute build action type did not match expected var type");
1044
1045 item = attribute.build(PropertyAttributeArgs {
1046 input: item,
1047 when_conditions_data: data,
1048 });
1049 }
1050 item
1051}
1052
1053#[doc(hidden)]
1054pub fn new_dyn_var<'a, T: VarValue>(
1055 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1056 attributes: impl Iterator<Item = (&'a dyn AnyPropertyAttribute, &'a [Option<PropertyAttributeWhenData>])>,
1057) -> Var<T> {
1058 let item = new_dyn_var_build(inputs, std::any::TypeId::of::<T>());
1059 let item = item.downcast::<T>().expect("input did not match expected var types");
1060 apply_attributes(item, attributes)
1061}
1062fn new_dyn_var_build(inputs: &mut std::vec::IntoIter<Box<dyn Any>>, value_type: TypeId) -> AnyVar {
1063 let item = inputs.next().expect("missing input");
1064
1065 match item.downcast::<AnyWhenVarBuilder>() {
1066 Ok(builder) => builder.build(value_type),
1067 Err(item) => *item.downcast::<AnyVar>().expect("input did not match expected var types"),
1068 }
1069}
1070
1071#[doc(hidden)]
1072pub fn new_dyn_ui_node<'a>(
1073 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1074 attributes: impl Iterator<Item = (&'a dyn AnyPropertyAttribute, &'a [Option<PropertyAttributeWhenData>])>,
1075) -> ArcNode {
1076 let item = inputs.next().expect("missing input");
1077
1078 let item = match item.downcast::<WhenUiNodeBuilder>() {
1079 Ok(builder) => ArcNode::new(builder.build()),
1080 Err(item) => *item.downcast::<ArcNode>().expect("input did not match expected UiNode types"),
1081 };
1082 apply_attributes(item, attributes)
1083}
1084
1085#[doc(hidden)]
1086pub fn new_dyn_handler<'a, A: Clone + 'static>(
1087 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1088 attributes: impl Iterator<Item = (&'a dyn AnyPropertyAttribute, &'a [Option<PropertyAttributeWhenData>])>,
1089) -> ArcHandler<A> {
1090 let item = inputs.next().expect("missing input");
1091
1092 let item = match item.downcast::<AnyWhenArcHandlerBuilder>() {
1093 Ok(builder) => builder.build(),
1094 Err(item) => *item
1095 .downcast::<ArcHandler<A>>()
1096 .expect("input did not match expected Handler types"),
1097 };
1098
1099 apply_attributes(item, attributes)
1100}
1101
1102#[doc(hidden)]
1103pub fn new_dyn_other<'a, T: Any + Send>(
1104 inputs: &mut std::vec::IntoIter<Box<dyn Any>>,
1105 attributes: impl Iterator<Item = (&'a dyn AnyPropertyAttribute, &'a [Option<PropertyAttributeWhenData>])>,
1106) -> T {
1107 let item = *inputs
1108 .next()
1109 .expect("missing input")
1110 .downcast::<T>()
1111 .expect("input did not match expected var type");
1112
1113 apply_attributes(item, attributes)
1114}
1115
1116#[derive(Clone, PartialEq)]
1120pub struct UiNodeInWhenExprError;
1121impl fmt::Debug for UiNodeInWhenExprError {
1122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1123 write!(f, "{self}")
1124 }
1125}
1126impl fmt::Display for UiNodeInWhenExprError {
1127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1128 write!(f, "cannot ref `UiNode` in when expression, only var and value properties allowed")
1129 }
1130}
1131impl std::error::Error for UiNodeInWhenExprError {}
1132
1133#[derive(Clone, PartialEq)]
1137pub struct HandlerInWhenExprError;
1138impl fmt::Debug for HandlerInWhenExprError {
1139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1140 write!(f, "{self}")
1141 }
1142}
1143impl fmt::Display for HandlerInWhenExprError {
1144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1145 write!(
1146 f,
1147 "cannot ref `Handler<A>` in when expression, only var and value properties allowed"
1148 )
1149 }
1150}
1151impl std::error::Error for HandlerInWhenExprError {}
1152
1153#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
1161pub struct Importance(pub u32);
1162impl Importance {
1163 pub const WIDGET: Importance = Importance(1000);
1165 pub const INSTANCE: Importance = Importance(1000 * 10);
1167}
1168impl_from_and_into_var! {
1169 fn from(imp: u32) -> Importance {
1170 Importance(imp)
1171 }
1172}
1173
1174unique_id_32! {
1175 pub struct PropertyId;
1177}
1178zng_unique_id::impl_unique_id_bytemuck!(PropertyId);
1179impl fmt::Debug for PropertyId {
1180 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1181 f.debug_tuple("PropertyId").field(&self.get()).finish()
1182 }
1183}
1184
1185#[derive(Clone, Copy, Debug)]
1191#[non_exhaustive]
1192pub struct WidgetType {
1193 pub type_id: TypeId,
1195 pub path: &'static str,
1197 pub location: SourceLocation,
1199}
1200impl WidgetType {
1201 #[doc(hidden)]
1202 pub fn new(type_id: TypeId, path: &'static str, location: SourceLocation) -> Self {
1203 Self { type_id, path, location }
1204 }
1205
1206 pub fn name(&self) -> &'static str {
1208 self.path.rsplit_once(':').map(|(_, n)| n).unwrap_or(self.path)
1209 }
1210}
1211impl PartialEq for WidgetType {
1212 fn eq(&self, other: &Self) -> bool {
1213 self.type_id == other.type_id
1214 }
1215}
1216impl Eq for WidgetType {}
1217impl std::hash::Hash for WidgetType {
1218 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1219 self.type_id.hash(state);
1220 }
1221}
1222
1223#[derive(Clone, Copy, Debug)]
1225pub enum WhenInputMember {
1226 Named(&'static str),
1228 Index(usize),
1230}
1231
1232#[derive(Clone)]
1234pub struct WhenInput {
1235 pub property: PropertyId,
1237 pub member: WhenInputMember,
1239 pub var: WhenInputVar,
1241 pub property_default: Option<fn() -> Box<dyn PropertyArgs>>,
1243
1244 #[doc(hidden)] pub _non_exhaustive: (),
1246}
1247impl fmt::Debug for WhenInput {
1248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1249 f.debug_struct("WhenInput")
1250 .field("property", &self.property)
1251 .field("member", &self.member)
1252 .finish_non_exhaustive()
1253 }
1254}
1255
1256context_local! {
1257 static WHEN_INPUT_CONTEXT_INIT_ID: ContextInitHandle = ContextInitHandle::no_context();
1259}
1260
1261#[derive(Clone)]
1263pub struct WhenInputVar {
1264 var: Arc<Mutex<Vec<(WeakContextInitHandle, AnyVar)>>>,
1265}
1266impl WhenInputVar {
1267 pub fn new<T: VarValue>() -> (Self, Var<T>) {
1271 let arc = Arc::new(Mutex::new(vec![]));
1272 (
1273 WhenInputVar { var: arc.clone() },
1274 contextual_var(move || {
1275 let mut data = arc.lock();
1276
1277 let current_id = WHEN_INPUT_CONTEXT_INIT_ID.get();
1278 let current_id = current_id.downgrade();
1279
1280 let mut r = None;
1281 data.retain(|(id, val)| {
1282 let retain = id.is_alive();
1283 if retain && id == ¤t_id {
1284 r = Some(val.clone());
1285 }
1286 retain
1287 });
1288 match r {
1289 Some(r) => r,
1290 None => {
1291 if !data.is_empty() {
1293 let last = data.len() - 1;
1295 let last = &data[last];
1296 tracing::error!(
1297 "when input not inited for context {:?}, using value from {:?} to avoid crash",
1298 current_id,
1299 last.0
1300 );
1301 last.1.clone()
1302 } else {
1303 panic!("when input not inited for context {current_id:?}")
1305 }
1306 }
1307 }
1308 .downcast()
1309 .expect("incorrect when input var type")
1310 }),
1311 )
1312 }
1313
1314 fn set(&self, handle: WeakContextInitHandle, var: AnyVar) {
1315 let mut data = self.var.lock();
1316
1317 if let Some(i) = data.iter().position(|(i, _)| i == &handle) {
1318 data[i].1 = var;
1319 } else {
1320 data.push((handle, var));
1321 }
1322 }
1323}
1324
1325type PropertyAttributeWhenData = Arc<dyn Any + Send + Sync>;
1326type PropertyAttributeWhenDefault = Arc<dyn Fn() -> Vec<Box<dyn AnyPropertyAttribute>> + Send + Sync>;
1327
1328#[derive(Clone)]
1330#[non_exhaustive]
1331pub struct PropertyAttributeWhen {
1332 pub data: PropertyAttributeWhenData,
1334 pub default: Option<PropertyAttributeWhenDefault>,
1340}
1341impl PropertyAttributeWhen {
1342 pub fn new<D, F>(data: D, default_action: F) -> Self
1344 where
1345 D: Any + Send + Sync + 'static,
1346 F: Fn() -> Vec<Box<dyn AnyPropertyAttribute>> + Send + Sync + 'static,
1347 {
1348 Self {
1349 data: Arc::new(data),
1350 default: Some(Arc::new(default_action)),
1351 }
1352 }
1353
1354 pub fn new_no_default(data: impl Any + Send + Sync + 'static) -> Self {
1356 Self {
1357 data: Arc::new(data),
1358 default: None,
1359 }
1360 }
1361}
1362
1363#[derive(Clone)]
1365#[non_exhaustive]
1366pub struct WhenInfo {
1367 pub inputs: Box<[WhenInput]>,
1375
1376 pub state: Var<bool>,
1380
1381 pub assigns: Vec<Box<dyn PropertyArgs>>,
1384
1385 pub attributes_data: Vec<((PropertyId, &'static str), PropertyAttributeWhen)>,
1387
1388 pub expr: &'static str,
1390
1391 pub location: SourceLocation,
1393}
1394impl fmt::Debug for WhenInfo {
1395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1396 struct DebugBuildActions<'a>(&'a WhenInfo);
1397 impl fmt::Debug for DebugBuildActions<'_> {
1398 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1399 f.debug_list().entries(self.0.attributes_data.iter().map(|(k, _)| k)).finish()
1400 }
1401 }
1402
1403 f.debug_struct("WhenInfo")
1404 .field("inputs", &self.inputs)
1405 .field("state", &self.state.get_debug(false))
1406 .field("assigns", &self.assigns)
1407 .field("attributes_data", &DebugBuildActions(self))
1408 .field("expr", &self.expr)
1409 .finish()
1410 }
1411}
1412impl Clone for Box<dyn PropertyArgs> {
1413 fn clone(&self) -> Self {
1414 PropertyArgs::clone_boxed(&**self)
1415 }
1416}
1417impl fmt::Debug for &dyn PropertyArgs {
1418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1419 f.debug_struct("dyn PropertyArgs")
1420 .field("property", &self.property())
1421 .finish_non_exhaustive()
1422 }
1423}
1424impl fmt::Debug for Box<dyn PropertyArgs> {
1425 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1426 f.debug_struct("dyn PropertyArgs")
1427 .field("property", &self.property())
1428 .finish_non_exhaustive()
1429 }
1430}
1431
1432#[derive(Clone)]
1433struct WidgetItemPositioned {
1434 position: NestPosition,
1435 insert_idx: u32,
1436 item: WidgetItem,
1437}
1438impl WidgetItemPositioned {
1439 fn sort_key(&self) -> (NestPosition, u32) {
1440 (self.position, self.insert_idx)
1441 }
1442}
1443
1444#[derive(Clone, Debug)]
1445struct WhenItemPositioned {
1446 importance: Importance,
1447 insert_idx: u32,
1448 when: WhenInfo,
1449}
1450impl WhenItemPositioned {
1451 fn sort_key(&self) -> (Importance, u32) {
1452 (self.importance, self.insert_idx)
1453 }
1454}
1455
1456enum WidgetItem {
1457 Property {
1458 importance: Importance,
1459 args: Box<dyn PropertyArgs>,
1460 captured: bool,
1461 },
1462 Intrinsic {
1463 name: &'static str,
1464 new: Box<dyn FnOnce(UiNode) -> UiNode + Send + Sync>,
1465 },
1466}
1467impl Clone for WidgetItem {
1468 fn clone(&self) -> Self {
1469 match self {
1470 Self::Property {
1471 importance,
1472 args,
1473 captured,
1474 } => Self::Property {
1475 importance: *importance,
1476 captured: *captured,
1477 args: args.clone(),
1478 },
1479 Self::Intrinsic { .. } => unreachable!("only WidgetBuilder clones, and it does not insert intrinsic"),
1480 }
1481 }
1482}
1483
1484type PropertyAttributesMap = HashMap<(PropertyId, &'static str), (Importance, Vec<Box<dyn AnyPropertyAttribute>>)>;
1486type PropertyAttributesVec = Vec<((PropertyId, &'static str), (Importance, Vec<Box<dyn AnyPropertyAttribute>>))>;
1487
1488pub struct WidgetBuilder {
1490 widget_type: WidgetType,
1491
1492 insert_idx: u32,
1493 p: WidgetBuilderProperties,
1494 unset: HashMap<PropertyId, Importance>,
1495
1496 whens: Vec<WhenItemPositioned>,
1497 when_insert_idx: u32,
1498
1499 p_attributes: PropertyAttributesMap,
1500 p_attributes_unset: HashMap<(PropertyId, &'static str), Importance>,
1501
1502 build_actions: Vec<Arc<Mutex<dyn FnMut(&mut WidgetBuilding) + Send>>>,
1503 pre_build_actions: Vec<Arc<Mutex<dyn FnMut(&mut WidgetBuilding) + Send>>>,
1504
1505 custom_build: Option<Arc<Mutex<dyn FnMut(WidgetBuilder) -> UiNode + Send>>>,
1506}
1507impl Clone for WidgetBuilder {
1508 fn clone(&self) -> Self {
1509 Self {
1510 widget_type: self.widget_type,
1511 p: WidgetBuilderProperties { items: self.items.clone() },
1512 p_attributes: self.p_attributes.clone(),
1513 insert_idx: self.insert_idx,
1514 unset: self.unset.clone(),
1515 p_attributes_unset: self.p_attributes_unset.clone(),
1516 whens: self.whens.clone(),
1517 when_insert_idx: self.when_insert_idx,
1518 build_actions: self.build_actions.clone(),
1519 pre_build_actions: self.pre_build_actions.clone(),
1520 custom_build: self.custom_build.clone(),
1521 }
1522 }
1523}
1524impl fmt::Debug for WidgetBuilder {
1525 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1526 struct PropertiesDebug<'a>(&'a WidgetBuilderProperties);
1527 impl fmt::Debug for PropertiesDebug<'_> {
1528 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1529 f.debug_list().entries(self.0.properties()).finish()
1530 }
1531 }
1532 f.debug_struct("WidgetBuilder")
1533 .field("widget_type", &self.widget_type)
1534 .field("properties", &PropertiesDebug(&self.p))
1535 .field("unset", &self.unset)
1536 .field("whens", &self.whens)
1537 .field("build_actions.len", &self.build_actions.len())
1538 .field("pre_build_actions.len", &self.pre_build_actions.len())
1539 .field("is_custom_build", &self.is_custom_build())
1540 .finish()
1541 }
1542}
1543impl WidgetBuilder {
1544 pub fn new(widget: WidgetType) -> Self {
1546 Self {
1547 widget_type: widget,
1548 p: WidgetBuilderProperties { items: Default::default() },
1549 insert_idx: 0,
1550 unset: Default::default(),
1551 whens: Default::default(),
1552 p_attributes: Default::default(),
1553 p_attributes_unset: Default::default(),
1554 when_insert_idx: 0,
1555 build_actions: Default::default(),
1556 pre_build_actions: Default::default(),
1557 custom_build: Default::default(),
1558 }
1559 }
1560
1561 pub fn widget_type(&self) -> WidgetType {
1563 self.widget_type
1564 }
1565
1566 pub fn push_property(&mut self, importance: Importance, args: Box<dyn PropertyArgs>) {
1570 let pos = NestPosition::property(args.property().group);
1571 self.push_property_positioned(importance, pos, args);
1572 }
1573
1574 pub fn push_property_positioned(&mut self, importance: Importance, position: NestPosition, args: Box<dyn PropertyArgs>) {
1576 self.push_property_positioned_impl(importance, position, args, false)
1577 }
1578 fn push_property_positioned_impl(
1579 &mut self,
1580 importance: Importance,
1581 position: NestPosition,
1582 args: Box<dyn PropertyArgs>,
1583 captured: bool,
1584 ) {
1585 let insert_idx = self.insert_idx;
1586 self.insert_idx = insert_idx.wrapping_add(1);
1587
1588 let property_id = args.id();
1589 if let Some(i) = self.p.property_index(property_id) {
1590 match &self.p.items[i].item {
1591 WidgetItem::Property { importance: imp, .. } => {
1592 if *imp <= importance {
1593 self.p.items[i] = WidgetItemPositioned {
1595 position,
1596 insert_idx,
1597 item: WidgetItem::Property {
1598 importance,
1599 args,
1600 captured,
1601 },
1602 };
1603 }
1604 }
1605 WidgetItem::Intrinsic { .. } => unreachable!(),
1606 }
1607 } else {
1608 if let Some(imp) = self.unset.get(&property_id)
1609 && *imp >= importance
1610 {
1611 return; }
1613 self.p.items.push(WidgetItemPositioned {
1614 position,
1615 insert_idx,
1616 item: WidgetItem::Property {
1617 importance,
1618 args,
1619 captured,
1620 },
1621 });
1622 }
1623 }
1624
1625 pub fn push_when(&mut self, importance: Importance, mut when: WhenInfo) {
1627 let insert_idx = self.when_insert_idx;
1628 self.when_insert_idx = insert_idx.wrapping_add(1);
1629
1630 when.assigns.retain(|a| {
1631 if let Some(imp) = self.unset.get(&a.id()) {
1632 *imp < importance
1633 } else {
1634 true
1635 }
1636 });
1637
1638 if !when.assigns.is_empty() {
1639 self.whens.push(WhenItemPositioned {
1640 importance,
1641 insert_idx,
1642 when,
1643 });
1644 }
1645 }
1646
1647 pub fn push_unset(&mut self, importance: Importance, property_id: PropertyId) {
1649 let check;
1650 match self.unset.entry(property_id) {
1651 hash_map::Entry::Occupied(mut e) => {
1652 let i = e.get_mut();
1653 check = *i < importance;
1654 *i = importance;
1655 }
1656 hash_map::Entry::Vacant(e) => {
1657 check = true;
1658 e.insert(importance);
1659 }
1660 }
1661
1662 if check {
1663 if let Some(i) = self.p.property_index(property_id) {
1664 match &self.p.items[i].item {
1665 WidgetItem::Property { importance: imp, .. } => {
1666 if *imp <= importance {
1667 self.p.items.swap_remove(i);
1668 }
1669 }
1670 WidgetItem::Intrinsic { .. } => unreachable!(),
1671 }
1672 }
1673
1674 self.whens.retain_mut(|w| {
1675 if w.importance <= importance {
1676 w.when.assigns.retain(|a| a.id() != property_id);
1677 !w.when.assigns.is_empty()
1678 } else {
1679 true
1680 }
1681 });
1682 }
1683 }
1684
1685 pub fn push_property_attribute(
1690 &mut self,
1691 property_id: PropertyId,
1692 attribute_name: &'static str,
1693 importance: Importance,
1694 input_actions: Vec<Box<dyn AnyPropertyAttribute>>,
1695 ) {
1696 match self.p_attributes.entry((property_id, attribute_name)) {
1697 hash_map::Entry::Occupied(mut e) => {
1698 if e.get().0 < importance {
1699 e.insert((importance, input_actions));
1700 }
1701 }
1702 hash_map::Entry::Vacant(e) => {
1703 if let Some(imp) = self.p_attributes_unset.get(&(property_id, attribute_name))
1704 && *imp >= importance
1705 {
1706 return;
1708 }
1709 e.insert((importance, input_actions));
1710 }
1711 }
1712 }
1713
1714 pub fn push_unset_property_attribute(&mut self, property_id: PropertyId, attribute_name: &'static str, importance: Importance) {
1718 let mut check = false;
1719 match self.p_attributes_unset.entry((property_id, attribute_name)) {
1720 hash_map::Entry::Occupied(mut e) => {
1721 if *e.get() < importance {
1722 e.insert(importance);
1723 check = true;
1724 }
1725 }
1726 hash_map::Entry::Vacant(e) => {
1727 e.insert(importance);
1728 check = true;
1729 }
1730 }
1731 if check {
1732 self.p_attributes.retain(|_, (imp, _)| *imp > importance);
1733 }
1734 }
1735
1736 pub fn clear_property_attributes(&mut self) {
1738 self.p_attributes.clear();
1739 }
1740
1741 pub fn push_build_action(&mut self, action: impl FnMut(&mut WidgetBuilding) + Send + 'static) {
1748 self.build_actions.push(Arc::new(Mutex::new(action)))
1749 }
1750
1751 pub fn push_pre_build_action(&mut self, action: impl FnMut(&mut WidgetBuilding) + Send + 'static) {
1761 self.pre_build_actions.push(Arc::new(Mutex::new(action)))
1762 }
1763
1764 pub fn clear_build_actions(&mut self) {
1766 self.build_actions.clear();
1767 self.pre_build_actions.clear();
1768 }
1769
1770 pub fn is_custom_build(&self) -> bool {
1772 self.custom_build.is_some()
1773 }
1774
1775 pub fn set_custom_build(&mut self, build: impl FnMut(WidgetBuilder) -> UiNode + Send + 'static) {
1782 self.custom_build = Some(Arc::new(Mutex::new(build)));
1783 }
1784
1785 pub fn clear_custom_build(&mut self) {
1787 self.custom_build = None;
1788 }
1789
1790 pub fn extend(&mut self, other: WidgetBuilder) {
1800 self.extend_important(other, Importance(0));
1801 }
1802 pub fn extend_important(&mut self, other: WidgetBuilder, min_importance: Importance) {
1806 for (id, imp) in other.unset {
1807 if imp >= min_importance {
1808 self.push_unset(imp, id);
1809 }
1810 }
1811
1812 for ((id, name), imp) in other.p_attributes_unset {
1813 if imp >= min_importance {
1814 self.push_unset_property_attribute(id, name, imp);
1815 }
1816 }
1817
1818 for WidgetItemPositioned { position, item, .. } in other.p.items {
1819 match item {
1820 WidgetItem::Property {
1821 importance,
1822 args,
1823 captured,
1824 } => {
1825 if importance >= min_importance {
1826 self.push_property_positioned_impl(importance, position, args, captured);
1827 }
1828 }
1829 WidgetItem::Intrinsic { .. } => unreachable!(),
1830 }
1831 }
1832
1833 for w in other.whens {
1834 if w.importance >= min_importance {
1835 self.push_when(w.importance, w.when);
1836 }
1837 }
1838
1839 for ((id, name), (imp, action)) in other.p_attributes {
1840 if imp >= min_importance {
1841 self.push_property_attribute(id, name, imp, action);
1842 }
1843 }
1844
1845 for act in other.pre_build_actions {
1846 self.pre_build_actions.push(act);
1847 }
1848
1849 for act in other.build_actions {
1850 self.build_actions.push(act);
1851 }
1852
1853 if let Some(c) = other.custom_build {
1854 self.custom_build = Some(c);
1855 }
1856 }
1857
1858 pub fn has_properties(&self) -> bool {
1860 !self.p.items.is_empty()
1861 }
1862
1863 pub fn has_unsets(&self) -> bool {
1865 !self.unset.is_empty()
1866 }
1867
1868 pub fn has_whens(&self) -> bool {
1870 !self.whens.is_empty()
1871 }
1872
1873 pub fn split_off(&mut self, properties: impl IntoIterator<Item = PropertyId>, out: &mut WidgetBuilder) {
1880 self.split_off_impl(properties.into_iter().collect(), out)
1881 }
1882 fn split_off_impl(&mut self, properties: IdSet<PropertyId>, out: &mut WidgetBuilder) {
1883 let mut found = 0;
1884
1885 let mut i = 0;
1887 while i < self.items.len() && found < properties.len() {
1888 match &self.items[i].item {
1889 WidgetItem::Property { args, .. } if properties.contains(&args.id()) => match self.items.swap_remove(i) {
1890 WidgetItemPositioned {
1891 position,
1892 item: WidgetItem::Property { importance, args, .. },
1893 ..
1894 } => {
1895 out.push_property_positioned(importance, position, args);
1896 found += 1;
1897 }
1898 _ => unreachable!(),
1899 },
1900 _ => {
1901 i += 1;
1902 continue;
1903 }
1904 }
1905 }
1906
1907 i = 0;
1908 while i < self.whens.len() {
1909 let mut ai = 0;
1911 let mut moved_assigns = vec![];
1912 while ai < self.whens[i].when.assigns.len() {
1913 if properties.contains(&self.whens[i].when.assigns[ai].id()) {
1914 let args = self.whens[i].when.assigns.remove(ai);
1915 moved_assigns.push(args);
1916 } else {
1917 ai += 1;
1918 }
1919 }
1920
1921 if !moved_assigns.is_empty() {
1922 let out_imp;
1923 let out_when;
1924 if self.whens[i].when.assigns.is_empty() {
1925 let WhenItemPositioned { importance, mut when, .. } = self.whens.remove(i);
1927 when.assigns = moved_assigns;
1928
1929 out_imp = importance;
1930 out_when = when;
1931 } else {
1932 let WhenItemPositioned { importance, when, .. } = &self.whens[i];
1934 out_imp = *importance;
1935 out_when = WhenInfo {
1936 inputs: when.inputs.clone(),
1937 state: when.state.clone(),
1938 assigns: moved_assigns,
1939 attributes_data: when.attributes_data.clone(),
1940 expr: when.expr,
1941 location: when.location,
1942 };
1943
1944 i += 1;
1945 };
1946
1947 for input in out_when.inputs.iter() {
1949 if let Some(i) = self.property_index(input.property) {
1950 match &self.items[i] {
1951 WidgetItemPositioned {
1952 position,
1953 item: WidgetItem::Property { importance, args, .. },
1954 ..
1955 } => {
1956 out.push_property_positioned(*importance, *position, args.clone());
1957 }
1958 _ => unreachable!(),
1959 }
1960 }
1961 }
1962
1963 out.push_when(out_imp, out_when);
1964 } else {
1965 i += 1;
1966 }
1967 }
1968
1969 for id in properties {
1971 if let Some(imp) = self.unset.remove(&id) {
1972 out.push_unset(imp, id);
1973 }
1974 }
1975 }
1976
1977 pub fn build(self) -> UiNode {
1983 if let Some(custom) = self.custom_build.clone() {
1984 match custom.try_lock() {
1985 Some(mut c) => c(self),
1986 None => self.default_build(),
1987 }
1988 } else {
1989 self.default_build()
1990 }
1991 }
1992
1993 pub fn default_build(self) -> UiNode {
1997 #[cfg(feature = "inspector")]
1998 let builder = self.clone();
1999
2000 let mut building = WidgetBuilding {
2001 #[cfg(feature = "inspector")]
2002 builder: Some(builder),
2003 #[cfg(feature = "trace_widget")]
2004 trace_widget: true,
2005 #[cfg(feature = "trace_wgt_item")]
2006 trace_wgt_item: true,
2007
2008 widget_type: self.widget_type,
2009 p: self.p,
2010 child: None,
2011 build_action_property: None,
2012 };
2013
2014 let mut p_attributes = self.p_attributes.into_iter().collect();
2015
2016 let mut when_init_context_handle = None;
2017
2018 if !self.whens.is_empty() {
2019 let handle = ContextInitHandle::new();
2020 building.build_whens(self.whens, handle.downgrade(), &mut p_attributes);
2021 when_init_context_handle = Some(handle);
2022 }
2023
2024 if !p_attributes.is_empty() {
2025 building.build_p_attributes(p_attributes);
2026 }
2027
2028 for action in self.pre_build_actions.into_iter().rev() {
2029 (action.lock())(&mut building);
2030 }
2031 for action in self.build_actions {
2032 (action.lock())(&mut building);
2033 }
2034
2035 building.run_build_action_properties();
2036
2037 building.build(when_init_context_handle)
2038 }
2039}
2040impl ops::Deref for WidgetBuilder {
2041 type Target = WidgetBuilderProperties;
2042
2043 fn deref(&self) -> &Self::Target {
2044 &self.p
2045 }
2046}
2047impl ops::DerefMut for WidgetBuilder {
2048 fn deref_mut(&mut self) -> &mut Self::Target {
2049 &mut self.p
2050 }
2051}
2052
2053pub struct WidgetBuilding {
2061 #[cfg(feature = "inspector")]
2062 builder: Option<WidgetBuilder>,
2063 #[cfg(feature = "trace_widget")]
2064 trace_widget: bool,
2065 #[cfg(feature = "trace_wgt_item")]
2066 trace_wgt_item: bool,
2067
2068 widget_type: WidgetType,
2069 p: WidgetBuilderProperties,
2070 child: Option<UiNode>,
2071
2072 build_action_property: Option<PropertyInfo>,
2073}
2074impl WidgetBuilding {
2075 pub fn widget_type(&self) -> WidgetType {
2077 self.widget_type
2078 }
2079
2080 pub fn has_child(&self) -> bool {
2084 self.child.is_some()
2085 }
2086
2087 pub fn set_child(&mut self, node: impl IntoUiNode) {
2089 self.child = Some(node.into_node());
2090 }
2091
2092 #[cfg(feature = "inspector")]
2096 pub fn disable_inspector(&mut self) {
2097 self.builder = None;
2098 }
2099
2100 #[cfg(feature = "trace_widget")]
2104 pub fn disable_trace_widget(&mut self) {
2105 self.trace_widget = false;
2106 }
2107
2108 #[cfg(feature = "trace_wgt_item")]
2112 pub fn disable_trace_wgt_item(&mut self) {
2113 self.trace_wgt_item = false;
2114 }
2115
2116 pub fn push_intrinsic(
2120 &mut self,
2121 group: NestGroup,
2122 name: &'static str,
2123 intrinsic: impl FnOnce(UiNode) -> UiNode + Send + Sync + 'static,
2124 ) {
2125 self.push_intrinsic_positioned(NestPosition::intrinsic(group), name, intrinsic)
2126 }
2127
2128 pub fn push_intrinsic_positioned(
2132 &mut self,
2133 position: NestPosition,
2134 name: &'static str,
2135 intrinsic: impl FnOnce(UiNode) -> UiNode + Send + Sync + 'static,
2136 ) {
2137 self.items.push(WidgetItemPositioned {
2138 position,
2139 insert_idx: u32::MAX,
2140 item: WidgetItem::Intrinsic {
2141 name,
2142 new: Box::new(intrinsic),
2143 },
2144 });
2145 }
2146
2147 pub fn remove_property(&mut self, property_id: PropertyId) -> Option<BuilderProperty> {
2151 if let Some(i) = self.property_index(property_id) {
2152 match self.items.swap_remove(i) {
2153 WidgetItemPositioned {
2154 position,
2155 item:
2156 WidgetItem::Property {
2157 importance,
2158 args,
2159 captured,
2160 },
2161 ..
2162 } => Some(BuilderProperty {
2163 importance,
2164 position,
2165 args,
2166 captured,
2167 }),
2168 _ => unreachable!(),
2169 }
2170 } else {
2171 None
2172 }
2173 }
2174
2175 pub fn capture_property(&mut self, property_id: PropertyId) -> Option<BuilderPropertyRef<'_>> {
2180 self.capture_property_impl(property_id)
2181 }
2182
2183 pub fn capture_var<T>(&mut self, property_id: PropertyId) -> Option<Var<T>>
2185 where
2186 T: VarValue,
2187 {
2188 let p = self.capture_property(property_id)?;
2189 let var = p.args.downcast_var::<T>(0).clone();
2190 Some(var)
2191 }
2192
2193 pub fn capture_var_or_else<T, F>(&mut self, property_id: PropertyId, or_else: impl FnOnce() -> F) -> Var<T>
2195 where
2196 T: VarValue,
2197 F: IntoVar<T>,
2198 {
2199 match self.capture_var::<T>(property_id) {
2200 Some(var) => var,
2201 None => or_else().into_var(),
2202 }
2203 }
2204
2205 pub fn capture_var_or_default<T>(&mut self, property_id: PropertyId) -> Var<T>
2207 where
2208 T: VarValue + Default,
2209 {
2210 self.capture_var_or_else(property_id, T::default)
2211 }
2212
2213 pub fn capture_ui_node(&mut self, property_id: PropertyId) -> Option<UiNode> {
2215 let p = self.capture_property(property_id)?;
2216 let node = p.args.ui_node(0).take_on_init();
2217 Some(node)
2218 }
2219
2220 pub fn capture_ui_node_or_else(&mut self, property_id: PropertyId, or_else: impl FnOnce() -> UiNode) -> UiNode {
2222 match self.capture_ui_node(property_id) {
2223 Some(u) => u,
2224 None => or_else(),
2225 }
2226 }
2227
2228 pub fn capture_ui_node_or_nil(&mut self, property_id: PropertyId) -> UiNode {
2230 self.capture_ui_node_or_else(property_id, UiNode::nil)
2231 }
2232
2233 pub fn capture_handler<A: Clone + 'static>(&mut self, property_id: PropertyId) -> Option<ArcHandler<A>> {
2235 let p = self.capture_property(property_id)?;
2236 let handler = p.args.downcast_handler::<A>(0).clone();
2237 Some(handler)
2238 }
2239
2240 pub fn build_action_property(&mut self) -> Option<&PropertyInfo> {
2242 self.build_action_property.as_ref()
2243 }
2244
2245 pub fn expect_property_capture(&mut self) {
2250 #[cfg(debug_assertions)]
2251 if let Some(p_name) = self.build_action_property().map(|p| p.name) {
2252 tracing::error!(
2253 "capture only property `{}` is not captured in `{}!`, it will have no effect",
2254 p_name,
2255 self.widget_type.name()
2256 );
2257 }
2258 }
2259
2260 fn build_whens(
2261 &mut self,
2262 mut whens: Vec<WhenItemPositioned>,
2263 when_init_context_id: WeakContextInitHandle,
2264 attributes: &mut PropertyAttributesVec,
2265 ) {
2266 whens.sort_unstable_by_key(|w| w.sort_key());
2267
2268 struct Input<'a> {
2269 input: &'a WhenInput,
2270 item_idx: usize,
2271 }
2272 let mut inputs = vec![];
2273
2274 struct Assign {
2275 item_idx: usize,
2276 builder: Vec<Box<dyn Any>>,
2277 when_count: usize,
2278 attrs_data: HashMap<&'static str, (Vec<Option<PropertyAttributeWhenData>>, Option<PropertyAttributeWhenDefault>)>,
2281 }
2282 let mut assigns = IdMap::default();
2283
2284 'when: for WhenItemPositioned { when, .. } in whens.iter().rev() {
2286 let valid_inputs = inputs.len();
2288 let valid_items = self.p.items.len();
2289 for input in when.inputs.iter() {
2290 if let Some(i) = self.property_index(input.property) {
2291 inputs.push(Input { input, item_idx: i })
2292 } else if let Some(default) = input.property_default {
2293 let args = default();
2294 self.p.items.push(WidgetItemPositioned {
2295 position: NestPosition::property(args.property().group),
2296 insert_idx: u32::MAX,
2297 item: WidgetItem::Property {
2298 importance: Importance::WIDGET,
2299 args,
2300 captured: false,
2301 },
2302 });
2303 inputs.push(Input {
2304 input,
2305 item_idx: self.p.items.len() - 1,
2306 });
2307 } else {
2308 inputs.truncate(valid_inputs);
2309 self.p.items.truncate(valid_items);
2310 continue 'when;
2311 }
2312 }
2313
2314 let mut any_assign = false;
2315 'assign: for assign in when.assigns.iter() {
2317 let id = assign.id();
2318 let assign_info;
2319 let i;
2320 if let Some(idx) = self.property_index(id) {
2321 assign_info = assign.property();
2322 i = idx;
2323 } else if let Some(default) = assign.property().default {
2324 let args = default();
2325 assign_info = args.property();
2326 i = self.p.items.len();
2327 self.p.items.push(WidgetItemPositioned {
2328 position: NestPosition::property(args.property().group),
2329 insert_idx: u32::MAX,
2330 item: WidgetItem::Property {
2331 importance: Importance::WIDGET,
2332 args,
2333 captured: false,
2334 },
2335 });
2336 } else {
2337 tracing::warn!(
2338 "property `{}` ignored, it is only set in `when` block and has no default value",
2339 assign.property().name
2340 );
2341 continue;
2342 }
2343
2344 any_assign = true;
2345
2346 let default_args = match &self.items[i].item {
2347 WidgetItem::Property { args, .. } => args,
2348 WidgetItem::Intrinsic { .. } => unreachable!(),
2349 };
2350 let info = default_args.property();
2351
2352 for (default_info, assign_info) in info.inputs.iter().zip(assign_info.inputs.iter()) {
2353 if default_info.ty != assign_info.ty {
2354 continue 'assign;
2356 }
2357 }
2358
2359 let entry = match assigns.entry(id) {
2360 IdEntry::Occupied(e) => e.into_mut(),
2361 IdEntry::Vacant(e) => e.insert(Assign {
2362 item_idx: i,
2363 builder: info
2364 .inputs
2365 .iter()
2366 .enumerate()
2367 .map(|(i, input)| match input.kind {
2368 InputKind::Var => Box::new(AnyWhenVarBuilder::new(default_args.var(i).clone())) as _,
2369 InputKind::UiNode => Box::new(WhenUiNodeBuilder::new(default_args.ui_node(i).take_on_init())) as _,
2370 InputKind::Handler => Box::new(AnyWhenArcHandlerBuilder::new(default_args.handler(i).clone_boxed())) as _,
2371 InputKind::Value => panic!("can only assign vars in when blocks"),
2372 })
2373 .collect(),
2374 when_count: 0,
2375 attrs_data: Default::default(),
2376 }),
2377 };
2378 entry.when_count += 1;
2379
2380 for (i, (input, entry)) in info.inputs.iter().zip(entry.builder.iter_mut()).enumerate() {
2381 match input.kind {
2382 InputKind::Var => {
2383 let entry = entry.downcast_mut::<AnyWhenVarBuilder>().unwrap();
2384 let value = assign.var(i).clone();
2385 entry.push(when.state.clone(), value);
2386 }
2387 InputKind::UiNode => {
2388 let entry = entry.downcast_mut::<WhenUiNodeBuilder>().unwrap();
2389 let node = assign.ui_node(i).take_on_init();
2390 entry.push(when.state.clone(), node);
2391 }
2392 InputKind::Handler => {
2393 let entry = entry.downcast_mut::<AnyWhenArcHandlerBuilder>().unwrap();
2394 let handler = assign.handler(i).clone_boxed();
2395 entry.push(when.state.clone(), handler);
2396 }
2397 InputKind::Value => panic!("cannot assign `Value` in when blocks"),
2398 }
2399 }
2400
2401 for ((property_id, attr_key), action) in &when.attributes_data {
2402 if *property_id == id {
2403 match entry.attrs_data.entry(*attr_key) {
2404 hash_map::Entry::Occupied(mut e) => {
2405 let e = e.get_mut();
2406 for _ in e.0.len()..(entry.when_count - 1) {
2407 e.0.push(None);
2408 }
2409 e.0.push(Some(action.data.clone()));
2410 if action.default.is_some() && e.1.is_none() {
2411 e.1.clone_from(&action.default);
2412 }
2413 }
2414 hash_map::Entry::Vacant(e) => {
2415 let mut a = Vec::with_capacity(entry.when_count);
2416 for _ in 0..(entry.when_count - 1) {
2417 a.push(None);
2418 }
2419 a.push(Some(action.data.clone()));
2420 e.insert((a, action.default.clone()));
2421 }
2422 }
2423 }
2424 }
2425 }
2426
2427 if !any_assign {
2428 inputs.truncate(valid_inputs);
2429 self.p.items.truncate(valid_items);
2430 }
2431 }
2432
2433 for Input { input, item_idx } in inputs {
2434 let args = match &self.items[item_idx].item {
2435 WidgetItem::Property { args, .. } => args,
2436 WidgetItem::Intrinsic { .. } => unreachable!(),
2437 };
2438 let info = args.property();
2439
2440 let member_i = match input.member {
2441 WhenInputMember::Named(name) => info.input_idx(name).expect("when ref named input not found"),
2442 WhenInputMember::Index(i) => i,
2443 };
2444
2445 let actual = match info.inputs[member_i].kind {
2446 InputKind::Var => args.var(member_i).clone(),
2447 InputKind::Value => any_const_var(args.value(member_i).clone_boxed()),
2448 _ => panic!("can only ref var or values in when expr"),
2449 };
2450 input.var.set(when_init_context_id.clone(), actual);
2451 }
2452
2453 for (
2454 _,
2455 Assign {
2456 item_idx,
2457 builder,
2458 when_count,
2459 attrs_data: mut actions_data,
2460 },
2461 ) in assigns
2462 {
2463 let args = match &mut self.items[item_idx].item {
2464 WidgetItem::Property { args, .. } => args,
2465 WidgetItem::Intrinsic { .. } => unreachable!(),
2466 };
2467
2468 let mut attrs = vec![];
2469 let mut attrs_data = vec![];
2470 if !attributes.is_empty() {
2471 let p_id = args.id();
2472 while let Some(i) = attributes.iter().position(|((id, _), _)| *id == p_id) {
2473 let ((_, action_key), (_, a)) = attributes.swap_remove(i);
2474 attrs.push(a);
2475
2476 if let Some(data) = actions_data.remove(action_key) {
2477 let mut data = data.clone();
2478 for _ in data.0.len()..when_count {
2479 data.0.push(None);
2480 }
2481 attrs_data.push(data.0);
2482 }
2483 }
2484 }
2485
2486 for (_, (mut data, default)) in actions_data {
2487 if let Some(default) = default {
2488 let action = default();
2489 for _ in data.len()..when_count {
2490 data.push(None);
2491 }
2492
2493 attrs.push(action);
2494 attrs_data.push(data);
2495 }
2496 }
2497
2498 *args = (args.property().new)(PropertyNewArgs {
2499 args: builder,
2500 attributes: attrs,
2501 attributes_when_data: attrs_data,
2502 });
2503 }
2504 }
2505
2506 fn build_p_attributes(&mut self, mut attributes: PropertyAttributesVec) {
2507 while !attributes.is_empty() {
2508 let ((p_id, _), (_, a)) = attributes.swap_remove(0);
2509 let mut attrs = vec![a];
2510
2511 while let Some(i) = attributes.iter().position(|((id, _), _)| *id == p_id) {
2512 let (_, (_, a)) = attributes.swap_remove(i);
2513 attrs.push(a);
2514 }
2515
2516 if let Some(i) = self.property_index(p_id) {
2517 match &mut self.items[i].item {
2518 WidgetItem::Property { args, .. } => *args = args.new_build(attrs, vec![]),
2519 WidgetItem::Intrinsic { .. } => unreachable!(),
2520 }
2521 }
2522 }
2523 }
2524
2525 fn run_build_action_properties(&mut self) {
2526 if self.items.is_empty() {
2527 return;
2528 }
2529
2530 self.items.sort_unstable_by_key(|b| b.sort_key());
2532
2533 let mut any = false;
2534 let mut i = self.items.len();
2535 loop {
2536 i -= 1;
2537 if let WidgetItem::Property { args, captured, .. } = &self.p.items[i].item
2538 && !captured
2539 {
2540 let p = args.property();
2541 if p.build_action {
2542 any = true;
2543 self.build_action_property = Some(p);
2544 args.clone_boxed().build_action(self);
2545 self.build_action_property = None;
2546 }
2547 }
2548 if i == 0 {
2549 break;
2550 }
2551 }
2552
2553 if any {
2554 self.items.sort_unstable_by_key(|b| b.sort_key());
2555 }
2556 }
2557
2558 fn build(mut self, when_init_context_handle: Option<ContextInitHandle>) -> UiNode {
2559 #[cfg(feature = "inspector")]
2560 let mut inspector_items = Vec::with_capacity(self.p.items.len());
2561
2562 let mut node = self.child.take().unwrap_or_else(|| FillUiNode.into_node());
2563 for WidgetItemPositioned { position, item, .. } in self.p.items.into_iter().rev() {
2564 match item {
2565 WidgetItem::Property { args, captured, .. } => {
2566 if !captured {
2567 node = args.instantiate(node);
2568
2569 #[cfg(feature = "trace_wgt_item")]
2570 if self.trace_wgt_item {
2571 let name = args.property().name;
2572 node = node.trace(move |mtd| crate::update::UpdatesTrace::property_span(name, mtd.mtd_name()));
2573 }
2574 }
2575
2576 #[cfg(feature = "inspector")]
2577 {
2578 if args.property().inputs.iter().any(|i| matches!(i.kind, InputKind::Var)) {
2579 node = crate::widget::inspector::actualize_var_info(node, args.id());
2580 }
2581
2582 inspector_items.push(crate::widget::inspector::InstanceItem::Property { args, captured });
2583 }
2584 }
2585 #[allow(unused_variables)] WidgetItem::Intrinsic { new, name } => {
2587 node = new(node);
2588 #[cfg(feature = "trace_wgt_item")]
2589 if self.trace_wgt_item {
2590 node = node.trace(move |mtd| crate::update::UpdatesTrace::intrinsic_span(name, mtd.mtd_name()));
2591 }
2592
2593 #[cfg(feature = "inspector")]
2594 inspector_items.push(crate::widget::inspector::InstanceItem::Intrinsic {
2595 group: position.group,
2596 name,
2597 });
2598
2599 #[cfg(not(feature = "inspector"))]
2600 let _ = position;
2601 }
2602 }
2603 }
2604
2605 #[cfg(feature = "inspector")]
2606 if let Some(builder) = self.builder {
2607 node = crate::widget::inspector::insert_widget_builder_info(
2608 node,
2609 crate::widget::inspector::InspectorInfo {
2610 builder,
2611 items: inspector_items.into_boxed_slice(),
2612 actual_vars: crate::widget::inspector::InspectorActualVars::default(),
2613 },
2614 );
2615 }
2616
2617 #[cfg(feature = "trace_widget")]
2618 if self.trace_widget {
2619 let name = self.widget_type.name();
2620 node = node.trace(move |op| crate::update::UpdatesTrace::widget_span(crate::widget::WIDGET.id(), name, op.mtd_name()));
2621 }
2622
2623 node = with_new_context_init_id(node);
2625
2626 if let Some(handle) = when_init_context_handle {
2627 let mut handle = Some(Arc::new(handle));
2629 node = crate::widget::node::match_node(node, move |c, op| {
2630 WHEN_INPUT_CONTEXT_INIT_ID.with_context(&mut handle, || c.op(op));
2631 });
2632 }
2633
2634 node
2635 }
2636}
2637impl ops::Deref for WidgetBuilding {
2638 type Target = WidgetBuilderProperties;
2639
2640 fn deref(&self) -> &Self::Target {
2641 &self.p
2642 }
2643}
2644impl ops::DerefMut for WidgetBuilding {
2645 fn deref_mut(&mut self) -> &mut Self::Target {
2646 &mut self.p
2647 }
2648}
2649
2650#[derive(Debug)]
2652#[non_exhaustive]
2653pub struct BuilderProperty {
2654 pub importance: Importance,
2656 pub position: NestPosition,
2658 pub args: Box<dyn PropertyArgs>,
2660 pub captured: bool,
2662}
2663
2664#[derive(Debug)]
2666#[non_exhaustive]
2667pub struct BuilderPropertyRef<'a> {
2668 pub importance: Importance,
2670 pub position: NestPosition,
2672 pub args: &'a dyn PropertyArgs,
2674 pub captured: bool,
2678}
2679
2680#[derive(Debug)]
2682#[non_exhaustive]
2683pub struct BuilderPropertyMut<'a> {
2684 pub importance: &'a mut Importance,
2686 pub position: &'a mut NestPosition,
2688 pub args: &'a mut Box<dyn PropertyArgs>,
2690 pub captured: &'a mut bool,
2694}
2695
2696pub struct WidgetBuilderProperties {
2698 items: Vec<WidgetItemPositioned>,
2699}
2700impl WidgetBuilderProperties {
2701 pub fn property(&self, property_id: PropertyId) -> Option<BuilderPropertyRef<'_>> {
2703 match self.property_index(property_id) {
2704 Some(i) => match &self.items[i].item {
2705 WidgetItem::Property {
2706 importance,
2707 args,
2708 captured,
2709 } => Some(BuilderPropertyRef {
2710 importance: *importance,
2711 position: self.items[i].position,
2712 args: &**args,
2713 captured: *captured,
2714 }),
2715 WidgetItem::Intrinsic { .. } => unreachable!(),
2716 },
2717 None => None,
2718 }
2719 }
2720
2721 pub fn property_mut(&mut self, property_id: PropertyId) -> Option<BuilderPropertyMut<'_>> {
2723 match self.property_index(property_id) {
2724 Some(i) => match &mut self.items[i] {
2725 WidgetItemPositioned {
2726 position,
2727 item:
2728 WidgetItem::Property {
2729 importance,
2730 args,
2731 captured,
2732 },
2733 ..
2734 } => Some(BuilderPropertyMut {
2735 importance,
2736 position,
2737 args,
2738 captured,
2739 }),
2740 _ => unreachable!(),
2741 },
2742 None => None,
2743 }
2744 }
2745
2746 pub fn properties(&self) -> impl Iterator<Item = BuilderPropertyRef<'_>> {
2750 self.items.iter().filter_map(|it| match &it.item {
2751 WidgetItem::Intrinsic { .. } => None,
2752 WidgetItem::Property {
2753 importance,
2754 args,
2755 captured,
2756 } => Some(BuilderPropertyRef {
2757 importance: *importance,
2758 position: it.position,
2759 args: &**args,
2760 captured: *captured,
2761 }),
2762 })
2763 }
2764
2765 pub fn properties_mut(&mut self) -> impl Iterator<Item = BuilderPropertyMut<'_>> {
2767 self.items.iter_mut().filter_map(|it| match &mut it.item {
2768 WidgetItem::Intrinsic { .. } => None,
2769 WidgetItem::Property {
2770 importance,
2771 args,
2772 captured,
2773 } => Some(BuilderPropertyMut {
2774 importance,
2775 position: &mut it.position,
2776 args,
2777 captured,
2778 }),
2779 })
2780 }
2781
2782 pub fn capture_value<T>(&mut self, property_id: PropertyId) -> Option<T>
2790 where
2791 T: VarValue,
2792 {
2793 let p = self.capture_property_impl(property_id)?;
2794 let value = p.args.downcast_value::<T>(0).clone();
2795 Some(value)
2796 }
2797
2798 pub fn capture_value_or_else<T>(&mut self, property_id: PropertyId, or_else: impl FnOnce() -> T) -> T
2800 where
2801 T: VarValue,
2802 {
2803 match self.capture_value(property_id) {
2804 Some(v) => v,
2805 None => or_else(),
2806 }
2807 }
2808
2809 pub fn capture_value_or_default<T>(&mut self, property_id: PropertyId) -> T
2811 where
2812 T: VarValue + Default,
2813 {
2814 self.capture_value_or_else(property_id, T::default)
2815 }
2816
2817 fn capture_property_impl(&mut self, property_id: PropertyId) -> Option<BuilderPropertyRef<'_>> {
2818 if let Some(i) = self.property_index(property_id) {
2819 match &mut self.items[i] {
2820 WidgetItemPositioned {
2821 position,
2822 item:
2823 WidgetItem::Property {
2824 importance,
2825 args,
2826 captured,
2827 },
2828 ..
2829 } => {
2830 *captured = true;
2831 Some(BuilderPropertyRef {
2832 importance: *importance,
2833 position: *position,
2834 args: &**args,
2835 captured: *captured,
2836 })
2837 }
2838 _ => unreachable!(),
2839 }
2840 } else {
2841 None
2842 }
2843 }
2844
2845 fn property_index(&self, property_id: PropertyId) -> Option<usize> {
2846 self.items.iter().position(|it| match &it.item {
2847 WidgetItem::Property { args, .. } => args.id() == property_id,
2848 WidgetItem::Intrinsic { .. } => false,
2849 })
2850 }
2851}
2852
2853pub trait AnyPropertyAttribute: crate::private::Sealed + Any + Send + Sync {
2855 fn as_any(&self) -> &dyn Any;
2857
2858 fn clone_boxed(&self) -> Box<dyn AnyPropertyAttribute>;
2860}
2861
2862#[non_exhaustive]
2864pub struct PropertyAttributeArgs<'a, I: Any + Send> {
2865 pub input: I,
2867 pub when_conditions_data: &'a [Option<PropertyAttributeWhenData>],
2871}
2872
2873pub struct PropertyAttribute<I: Any + Send>(Arc<Mutex<dyn FnMut(PropertyAttributeArgs<I>) -> I + Send>>);
2891impl<I: Any + Send> crate::private::Sealed for PropertyAttribute<I> {}
2892impl<I: Any + Send> Clone for PropertyAttribute<I> {
2893 fn clone(&self) -> Self {
2894 Self(self.0.clone())
2895 }
2896}
2897impl<I: Any + Send> AnyPropertyAttribute for PropertyAttribute<I> {
2898 fn clone_boxed(&self) -> Box<dyn AnyPropertyAttribute> {
2899 Box::new(self.clone())
2900 }
2901
2902 fn as_any(&self) -> &dyn Any {
2903 self
2904 }
2905}
2906impl<I: Any + Send> PropertyAttribute<I> {
2907 pub fn new(build: impl FnMut(PropertyAttributeArgs<I>) -> I + Send + 'static) -> Self {
2909 Self(Arc::new(Mutex::new(build)))
2910 }
2911
2912 pub fn no_op() -> Self {
2914 Self::new(|i| i.input)
2915 }
2916
2917 pub fn build(&self, args: PropertyAttributeArgs<I>) -> I {
2919 (self.0.lock())(args)
2920 }
2921}
2922impl Clone for Box<dyn AnyPropertyAttribute> {
2923 fn clone(&self) -> Self {
2924 self.clone_boxed()
2925 }
2926}
2927
2928pub struct PropertyInputTypes<Tuple>(std::marker::PhantomData<Tuple>);
2989impl<Tuple> PropertyInputTypes<Tuple> {
2990 pub const fn unit() -> Self {
2992 Self(std::marker::PhantomData)
2993 }
2994}
2995impl<Tuple> Clone for PropertyInputTypes<Tuple> {
2996 fn clone(&self) -> Self {
2997 *self
2998 }
2999}
3000impl<Tuple> Copy for PropertyInputTypes<Tuple> {}
3001unsafe impl<Tuple> Send for PropertyInputTypes<Tuple> {}
3003unsafe impl<Tuple> Sync for PropertyInputTypes<Tuple> {}