cranpose_ui/modifier/
semantics.rs1use std::{
2 cell::Cell,
3 fmt,
4 hash::{Hash, Hasher},
5 rc::Rc,
6};
7
8use cranpose_core::NodeId;
9use cranpose_foundation::{
10 DelegatableNode, ModifierNode, ModifierNodeChain, ModifierNodeContext, ModifierNodeElement,
11 NodeCapabilities, NodeState, SemanticsConfiguration, SemanticsNode as SemanticsNodeTrait,
12};
13
14use super::{Modifier, ModifierChainHandle};
15use crate::render_state::AppContextId;
16
17#[derive(Clone, Default)]
49pub struct SemanticsRequester {
50 binding: Rc<Cell<Option<SemanticsBinding>>>,
51}
52
53#[derive(Clone, Copy)]
54struct SemanticsBinding {
55 app_context: AppContextId,
56 node_id: NodeId,
57}
58
59impl SemanticsRequester {
60 pub fn new() -> Self {
61 Self::default()
62 }
63
64 pub fn invalidate(&self) {
70 if let Some(binding) = self.binding.get() {
71 crate::semantics_dispatch::schedule_semantics_invalidation_in(
72 binding.app_context,
73 binding.node_id,
74 );
75 }
76 }
77
78 pub fn node_id(&self) -> Option<NodeId> {
80 self.binding.get().map(|binding| binding.node_id)
81 }
82
83 fn bind(&self, binding: Option<SemanticsBinding>) {
84 self.binding.set(binding);
85 }
86
87 fn binding_here(node_id: Option<NodeId>) -> Option<SemanticsBinding> {
88 Some(SemanticsBinding {
89 app_context: crate::render_state::current_app_context_id_opt()?,
90 node_id: node_id?,
91 })
92 }
93}
94
95impl fmt::Debug for SemanticsRequester {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 f.debug_struct("SemanticsRequester")
98 .field("node_id", &self.node_id())
99 .finish()
100 }
101}
102
103pub struct SemanticsModifierNode {
104 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
105 state: NodeState,
106}
107
108impl SemanticsModifierNode {
109 pub fn new(recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>) -> Self {
110 Self {
111 recorder,
112 state: NodeState::new(),
113 }
114 }
115}
116
117impl DelegatableNode for SemanticsModifierNode {
118 fn node_state(&self) -> &NodeState {
119 &self.state
120 }
121}
122
123impl ModifierNode for SemanticsModifierNode {
124 fn as_semantics_node(&self) -> Option<&dyn SemanticsNodeTrait> {
125 Some(self)
126 }
127
128 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNodeTrait> {
129 Some(self)
130 }
131}
132
133pub struct SemanticsRequesterNode {
134 state: NodeState,
135 requester: SemanticsRequester,
136}
137
138impl SemanticsRequesterNode {
139 pub(crate) fn new(requester: SemanticsRequester) -> Self {
140 Self {
141 state: NodeState::new(),
142 requester,
143 }
144 }
145}
146
147impl DelegatableNode for SemanticsRequesterNode {
148 fn node_state(&self) -> &NodeState {
149 &self.state
150 }
151}
152
153impl ModifierNode for SemanticsRequesterNode {
154 fn on_attach(&mut self, context: &mut dyn ModifierNodeContext) {
155 self.state.set_attached(true);
156 self.requester
157 .bind(SemanticsRequester::binding_here(context.node_id()));
158 }
159
160 fn on_detach(&mut self) {
161 self.state.set_attached(false);
162 self.requester.bind(None);
163 }
164}
165
166#[derive(Clone)]
168pub struct SemanticsRequesterElement {
169 requester: SemanticsRequester,
170}
171
172impl SemanticsRequesterElement {
173 pub(crate) fn new(requester: SemanticsRequester) -> Self {
174 Self { requester }
175 }
176}
177
178impl fmt::Debug for SemanticsRequesterElement {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 f.write_str("SemanticsRequesterElement")
181 }
182}
183
184impl PartialEq for SemanticsRequesterElement {
185 fn eq(&self, other: &Self) -> bool {
186 Rc::ptr_eq(&self.requester.binding, &other.requester.binding)
187 }
188}
189
190impl Eq for SemanticsRequesterElement {}
191
192impl Hash for SemanticsRequesterElement {
193 fn hash<H: Hasher>(&self, state: &mut H) {
194 Rc::as_ptr(&self.requester.binding).hash(state);
195 }
196}
197
198impl ModifierNodeElement for SemanticsRequesterElement {
199 type Node = SemanticsRequesterNode;
200
201 fn create(&self) -> Self::Node {
202 SemanticsRequesterNode::new(self.requester.clone())
203 }
204
205 fn update(&self, node: &mut Self::Node) {
206 if !Rc::ptr_eq(&node.requester.binding, &self.requester.binding) {
207 let bound = node.requester.binding.get();
208 node.requester.bind(None);
209 node.requester = self.requester.clone();
210 node.requester.bind(bound);
211 }
212 }
213
214 fn inspector_name(&self) -> &'static str {
215 "semanticsRequester"
216 }
217
218 fn capabilities(&self) -> NodeCapabilities {
219 NodeCapabilities::NONE
220 }
221}
222
223impl SemanticsNodeTrait for SemanticsModifierNode {
224 fn merge_semantics(&self, config: &mut SemanticsConfiguration) {
225 (self.recorder)(config);
226 }
227}
228
229#[derive(Clone)]
230pub struct SemanticsElement {
231 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
232}
233
234impl SemanticsElement {
235 pub fn new(recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>) -> Self {
236 Self { recorder }
237 }
238}
239
240impl fmt::Debug for SemanticsElement {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 f.write_str("SemanticsElement")
243 }
244}
245
246impl PartialEq for SemanticsElement {
247 fn eq(&self, _other: &Self) -> bool {
248 true
249 }
250}
251
252impl Eq for SemanticsElement {}
253
254impl Hash for SemanticsElement {
255 fn hash<H: Hasher>(&self, state: &mut H) {
256 "semantics".hash(state);
257 }
258}
259
260impl ModifierNodeElement for SemanticsElement {
261 type Node = SemanticsModifierNode;
262
263 fn create(&self) -> Self::Node {
264 SemanticsModifierNode::new(self.recorder.clone())
265 }
266
267 fn update(&self, node: &mut Self::Node) {
268 node.recorder = self.recorder.clone();
269 }
270
271 fn capabilities(&self) -> NodeCapabilities {
272 NodeCapabilities::SEMANTICS
273 }
274
275 fn always_update(&self) -> bool {
276 true
277 }
278}
279
280fn merge_semantics_from_node(node: &dyn ModifierNode, config: &mut SemanticsConfiguration) -> bool {
281 let mut merged = false;
282
283 if let Some(semantics) = node.as_semantics_node() {
284 semantics.merge_semantics(config);
285 merged = true;
286 }
287
288 node.for_each_delegate(&mut |delegate| {
289 if merge_semantics_from_node(delegate, config) {
290 merged = true;
291 }
292 });
293
294 merged
295}
296
297pub fn collect_semantics_from_chain(chain: &ModifierNodeChain) -> Option<SemanticsConfiguration> {
299 if !chain.has_capability(NodeCapabilities::SEMANTICS) {
300 return None;
301 }
302
303 let mut config = SemanticsConfiguration::default();
304 let mut merged = false;
305 chain.for_each_node_with_capability(NodeCapabilities::SEMANTICS, |_ref, node| {
306 if merge_semantics_from_node(node, &mut config) {
307 merged = true;
308 }
309 });
310
311 if merged { Some(config) } else { None }
312}
313
314pub fn collect_semantics_from_modifier(modifier: &Modifier) -> Option<SemanticsConfiguration> {
316 let mut handle = ModifierChainHandle::new();
317 handle.update(modifier);
318 collect_semantics_from_chain(handle.chain())
319}