cranpose_foundation/modifier_helpers.rs
1//! Helper macros to reduce boilerplate when implementing modifier nodes.
2//!
3//! These helpers follow the Jetpack Compose pattern where setting capability
4//! bits + implementing the specialized trait is enough for the node to participate
5//! in the corresponding pipeline stage.
6
7/// Implements the as_draw_node methods for a type that implements DrawModifierNode.
8///
9/// # Example
10///
11/// ```text
12/// impl ModifierNode for MyNode {
13/// impl_draw_node!();
14/// }
15/// ```
16#[macro_export]
17macro_rules! impl_draw_node {
18 () => {
19 fn as_draw_node(&self) -> Option<&dyn $crate::DrawModifierNode> {
20 Some(self)
21 }
22
23 fn as_draw_node_mut(&mut self) -> Option<&mut dyn $crate::DrawModifierNode> {
24 Some(self)
25 }
26 };
27}
28
29/// Implements the as_pointer_input_node methods for a type that implements PointerInputNode.
30///
31/// # Example
32///
33/// ```text
34/// impl ModifierNode for MyNode {
35/// impl_pointer_input_node!();
36/// }
37/// ```
38#[macro_export]
39macro_rules! impl_pointer_input_node {
40 () => {
41 fn as_pointer_input_node(&self) -> Option<&dyn $crate::PointerInputNode> {
42 Some(self)
43 }
44
45 fn as_pointer_input_node_mut(&mut self) -> Option<&mut dyn $crate::PointerInputNode> {
46 Some(self)
47 }
48 };
49}
50
51/// Implements the as_semantics_node methods for a type that implements SemanticsNode.
52///
53/// # Example
54///
55/// ```text
56/// impl ModifierNode for MyNode {
57/// impl_semantics_node!();
58/// }
59/// ```
60#[macro_export]
61macro_rules! impl_semantics_node {
62 () => {
63 fn as_semantics_node(&self) -> Option<&dyn $crate::SemanticsNode> {
64 Some(self)
65 }
66
67 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn $crate::SemanticsNode> {
68 Some(self)
69 }
70 };
71}
72
73/// Implements the as_focus_node methods for a type that implements FocusNode.
74///
75/// # Example
76///
77/// ```text
78/// impl ModifierNode for MyNode {
79/// impl_focus_node!();
80/// }
81/// ```
82#[macro_export]
83macro_rules! impl_focus_node {
84 () => {
85 fn as_focus_node(&self) -> Option<&dyn $crate::FocusNode> {
86 Some(self)
87 }
88
89 fn as_focus_node_mut(&mut self) -> Option<&mut dyn $crate::FocusNode> {
90 Some(self)
91 }
92 };
93}
94
95/// Comprehensive macro that implements all capability-based methods for a modifier node.
96///
97/// This macro reduces boilerplate by automatically implementing the as_* methods
98/// for all specialized traits that the type implements. Use this as the primary
99/// way to declare which traits your node implements.
100///
101/// # Example
102///
103/// ```text
104/// impl ModifierNode for MyDrawNode {
105/// impl_modifier_node!(draw);
106/// }
107///
108/// impl ModifierNode for MyPointerNode {
109/// impl_modifier_node!(pointer_input);
110/// }
111///
112/// impl ModifierNode for MyComplexNode {
113/// impl_modifier_node!(draw, pointer_input, semantics);
114/// }
115/// ```
116#[macro_export]
117macro_rules! impl_modifier_node {
118 (draw) => {
119 $crate::impl_draw_node!();
120 };
121 (pointer_input) => {
122 $crate::impl_pointer_input_node!();
123 };
124 (semantics) => {
125 $crate::impl_semantics_node!();
126 };
127 (focus) => {
128 $crate::impl_focus_node!();
129 };
130 (draw, $($rest:tt)*) => {
131 $crate::impl_draw_node!();
132 $crate::impl_modifier_node!($($rest)*);
133 };
134 (pointer_input, $($rest:tt)*) => {
135 $crate::impl_pointer_input_node!();
136 $crate::impl_modifier_node!($($rest)*);
137 };
138 (semantics, $($rest:tt)*) => {
139 $crate::impl_semantics_node!();
140 $crate::impl_modifier_node!($($rest)*);
141 };
142 (focus, $($rest:tt)*) => {
143 $crate::impl_focus_node!();
144 $crate::impl_modifier_node!($($rest)*);
145 };
146}