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