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 {
63 Self::default()
64 }
65
66 pub fn invalidate(&self) {
72 if let Some(binding) = self.binding.get() {
73 crate::semantics_dispatch::schedule_semantics_invalidation_in(
74 binding.app_context,
75 binding.node_id,
76 );
77 }
78 }
79
80 pub fn node_id(&self) -> Option<NodeId> {
82 self.binding.get().map(|binding| binding.node_id)
83 }
84
85 fn bind(&self, binding: Option<SemanticsBinding>) {
86 self.binding.set(binding);
87 }
88
89 fn binding_here(node_id: Option<NodeId>) -> Option<SemanticsBinding> {
90 Some(SemanticsBinding {
91 app_context: crate::render_state::current_app_context_id_opt()?,
92 node_id: node_id?,
93 })
94 }
95}
96
97impl fmt::Debug for SemanticsRequester {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 f.debug_struct("SemanticsRequester")
100 .field("node_id", &self.node_id())
101 .finish()
102 }
103}
104
105pub(super) struct SemanticsModifierNode {
106 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
107 reads_live_state: bool,
109 state: NodeState,
110}
111
112impl SemanticsModifierNode {
113 pub(super) fn new(
116 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
117 reads_live_state: bool,
118 ) -> Self {
119 Self {
120 recorder,
121 reads_live_state,
122 state: NodeState::new(),
123 }
124 }
125}
126
127impl DelegatableNode for SemanticsModifierNode {
128 fn node_state(&self) -> &NodeState {
129 &self.state
130 }
131}
132
133impl ModifierNode for SemanticsModifierNode {
134 fn as_semantics_node(&self) -> Option<&dyn SemanticsNodeTrait> {
135 Some(self)
136 }
137
138 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNodeTrait> {
139 Some(self)
140 }
141}
142
143pub(crate) struct SemanticsRequesterNode {
144 state: NodeState,
145 requester: SemanticsRequester,
146}
147
148impl SemanticsRequesterNode {
149 pub(crate) fn new(requester: SemanticsRequester) -> Self {
150 Self {
151 state: NodeState::new(),
152 requester,
153 }
154 }
155}
156
157impl DelegatableNode for SemanticsRequesterNode {
158 fn node_state(&self) -> &NodeState {
159 &self.state
160 }
161}
162
163impl ModifierNode for SemanticsRequesterNode {
164 fn on_attach(&mut self, context: &mut dyn ModifierNodeContext) {
165 self.requester
166 .bind(SemanticsRequester::binding_here(context.node_id()));
167 }
168
169 fn on_detach(&mut self) {
170 self.requester.bind(None);
171 }
172}
173
174#[derive(Clone)]
175pub(crate) struct SemanticsRequesterElement {
176 requester: SemanticsRequester,
177}
178
179impl SemanticsRequesterElement {
180 pub(crate) fn new(requester: SemanticsRequester) -> Self {
181 Self { requester }
182 }
183}
184
185impl fmt::Debug for SemanticsRequesterElement {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 f.write_str("SemanticsRequesterElement")
188 }
189}
190
191impl PartialEq for SemanticsRequesterElement {
192 fn eq(&self, other: &Self) -> bool {
193 Rc::ptr_eq(&self.requester.binding, &other.requester.binding)
194 }
195}
196
197impl Eq for SemanticsRequesterElement {}
198
199impl Hash for SemanticsRequesterElement {
200 fn hash<H: Hasher>(&self, state: &mut H) {
201 Rc::as_ptr(&self.requester.binding).hash(state);
202 }
203}
204
205impl ModifierNodeElement for SemanticsRequesterElement {
206 type Node = SemanticsRequesterNode;
207
208 fn create(&self) -> Self::Node {
209 SemanticsRequesterNode::new(self.requester.clone())
210 }
211
212 fn update(&self, node: &mut Self::Node) {
213 if !Rc::ptr_eq(&node.requester.binding, &self.requester.binding) {
214 let bound = node.requester.binding.get();
215 node.requester.bind(None);
216 node.requester = self.requester.clone();
217 node.requester.bind(bound);
218 }
219 }
220
221 fn inspector_name(&self) -> &'static str {
222 "semanticsRequester"
223 }
224
225 fn capabilities(&self) -> NodeCapabilities {
226 NodeCapabilities::NONE
227 }
228}
229
230impl SemanticsNodeTrait for SemanticsModifierNode {
231 fn merge_semantics(&self, config: &mut SemanticsConfiguration) {
232 (self.recorder)(config);
233 }
234
235 fn reach(&self) -> cranpose_foundation::SemanticsReach {
236 cranpose_foundation::SemanticsReach::merged_by(self, self.reads_live_state)
237 }
238}
239
240#[derive(Clone)]
241pub(super) struct SemanticsElement {
242 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
243 reads_live_state: bool,
244}
245
246impl SemanticsElement {
247 pub(super) fn new(
250 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
251 reads_live_state: bool,
252 ) -> Self {
253 Self {
254 recorder,
255 reads_live_state,
256 }
257 }
258}
259
260impl fmt::Debug for SemanticsElement {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 f.write_str("SemanticsElement")
263 }
264}
265
266impl PartialEq for SemanticsElement {
267 fn eq(&self, _other: &Self) -> bool {
268 true
269 }
270}
271
272impl Eq for SemanticsElement {}
273
274impl Hash for SemanticsElement {
275 fn hash<H: Hasher>(&self, state: &mut H) {
276 "semantics".hash(state);
277 }
278}
279
280impl ModifierNodeElement for SemanticsElement {
281 type Node = SemanticsModifierNode;
282
283 fn create(&self) -> Self::Node {
284 SemanticsModifierNode::new(Rc::clone(&self.recorder), self.reads_live_state)
285 }
286
287 fn update(&self, node: &mut Self::Node) {
288 node.recorder = Rc::clone(&self.recorder);
289 node.reads_live_state = self.reads_live_state;
290 }
291
292 fn capabilities(&self) -> NodeCapabilities {
293 NodeCapabilities::SEMANTICS
294 }
295
296 fn always_update(&self) -> bool {
297 true
298 }
299}
300
301fn merge_semantics_from_node(node: &dyn ModifierNode, config: &mut SemanticsConfiguration) -> bool {
302 let mut merged = false;
303
304 if let Some(semantics) = node.as_semantics_node() {
305 semantics.merge_semantics(config);
306 merged = true;
307 }
308
309 node.for_each_delegate(&mut |delegate| {
310 if merge_semantics_from_node(delegate, config) {
311 merged = true;
312 }
313 });
314
315 merged
316}
317
318pub(crate) fn collect_semantics_from_chain(
319 chain: &ModifierNodeChain,
320) -> Option<SemanticsConfiguration> {
321 if !chain.has_capability(NodeCapabilities::SEMANTICS) {
322 return None;
323 }
324
325 let mut config = SemanticsConfiguration::default();
326 let mut merged = false;
327 chain.for_each_node_with_capability(NodeCapabilities::SEMANTICS, |_ref, node| {
328 if merge_semantics_from_node(node, &mut config) {
329 merged = true;
330 }
331 });
332
333 if merged { Some(config) } else { None }
334}
335
336fn reach_of_node(node: &dyn ModifierNode) -> cranpose_foundation::SemanticsReach {
337 let mut reach = node
338 .as_semantics_node()
339 .map(cranpose_foundation::SemanticsNode::reach)
340 .unwrap_or_default();
341 node.for_each_delegate(&mut |delegate| {
342 reach = reach.union(reach_of_node(delegate));
343 });
344 reach
345}
346
347pub(crate) fn semantics_reach_of_chain(
348 chain: &ModifierNodeChain,
349) -> cranpose_foundation::SemanticsReach {
350 let mut reach = cranpose_foundation::SemanticsReach::default();
351 if !chain.has_capability(NodeCapabilities::SEMANTICS) {
352 return reach;
353 }
354 chain.for_each_node_with_capability(NodeCapabilities::SEMANTICS, |_ref, node| {
355 reach = reach.union(reach_of_node(node));
356 });
357 reach
358}
359
360pub fn collect_semantics_from_modifier(modifier: &Modifier) -> Option<SemanticsConfiguration> {
362 let mut handle = ModifierChainHandle::new();
363 handle.update(modifier);
364 collect_semantics_from_chain(handle.chain())
365}