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 struct SemanticsModifierNode {
106 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
107 reads_live_state: bool,
109 state: NodeState,
110}
111
112impl SemanticsModifierNode {
113 pub fn new(recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>, reads_live_state: bool) -> Self {
116 Self {
117 recorder,
118 reads_live_state,
119 state: NodeState::new(),
120 }
121 }
122}
123
124impl DelegatableNode for SemanticsModifierNode {
125 fn node_state(&self) -> &NodeState {
126 &self.state
127 }
128}
129
130impl ModifierNode for SemanticsModifierNode {
131 fn as_semantics_node(&self) -> Option<&dyn SemanticsNodeTrait> {
132 Some(self)
133 }
134
135 fn as_semantics_node_mut(&mut self) -> Option<&mut dyn SemanticsNodeTrait> {
136 Some(self)
137 }
138}
139
140pub struct SemanticsRequesterNode {
141 state: NodeState,
142 requester: SemanticsRequester,
143}
144
145impl SemanticsRequesterNode {
146 pub(crate) fn new(requester: SemanticsRequester) -> Self {
147 Self {
148 state: NodeState::new(),
149 requester,
150 }
151 }
152}
153
154impl DelegatableNode for SemanticsRequesterNode {
155 fn node_state(&self) -> &NodeState {
156 &self.state
157 }
158}
159
160impl ModifierNode for SemanticsRequesterNode {
161 fn on_attach(&mut self, context: &mut dyn ModifierNodeContext) {
162 self.state.set_attached(true);
163 self.requester
164 .bind(SemanticsRequester::binding_here(context.node_id()));
165 }
166
167 fn on_detach(&mut self) {
168 self.state.set_attached(false);
169 self.requester.bind(None);
170 }
171}
172
173#[derive(Clone)]
175pub 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 struct SemanticsElement {
242 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
243 reads_live_state: bool,
244}
245
246impl SemanticsElement {
247 pub fn new(recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>, reads_live_state: bool) -> Self {
250 Self {
251 recorder,
252 reads_live_state,
253 }
254 }
255}
256
257impl fmt::Debug for SemanticsElement {
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 f.write_str("SemanticsElement")
260 }
261}
262
263impl PartialEq for SemanticsElement {
264 fn eq(&self, _other: &Self) -> bool {
265 true
266 }
267}
268
269impl Eq for SemanticsElement {}
270
271impl Hash for SemanticsElement {
272 fn hash<H: Hasher>(&self, state: &mut H) {
273 "semantics".hash(state);
274 }
275}
276
277impl ModifierNodeElement for SemanticsElement {
278 type Node = SemanticsModifierNode;
279
280 fn create(&self) -> Self::Node {
281 SemanticsModifierNode::new(self.recorder.clone(), self.reads_live_state)
282 }
283
284 fn update(&self, node: &mut Self::Node) {
285 node.recorder = self.recorder.clone();
286 node.reads_live_state = self.reads_live_state;
287 }
288
289 fn capabilities(&self) -> NodeCapabilities {
290 NodeCapabilities::SEMANTICS
291 }
292
293 fn always_update(&self) -> bool {
294 true
295 }
296}
297
298fn merge_semantics_from_node(node: &dyn ModifierNode, config: &mut SemanticsConfiguration) -> bool {
299 let mut merged = false;
300
301 if let Some(semantics) = node.as_semantics_node() {
302 semantics.merge_semantics(config);
303 merged = true;
304 }
305
306 node.for_each_delegate(&mut |delegate| {
307 if merge_semantics_from_node(delegate, config) {
308 merged = true;
309 }
310 });
311
312 merged
313}
314
315pub fn collect_semantics_from_chain(chain: &ModifierNodeChain) -> Option<SemanticsConfiguration> {
317 if !chain.has_capability(NodeCapabilities::SEMANTICS) {
318 return None;
319 }
320
321 let mut config = SemanticsConfiguration::default();
322 let mut merged = false;
323 chain.for_each_node_with_capability(NodeCapabilities::SEMANTICS, |_ref, node| {
324 if merge_semantics_from_node(node, &mut config) {
325 merged = true;
326 }
327 });
328
329 if merged { Some(config) } else { None }
330}
331
332fn reach_of_node(node: &dyn ModifierNode) -> cranpose_foundation::SemanticsReach {
333 let mut reach = node
334 .as_semantics_node()
335 .map(cranpose_foundation::SemanticsNode::reach)
336 .unwrap_or_default();
337 node.for_each_delegate(&mut |delegate| {
338 reach = reach.union(reach_of_node(delegate));
339 });
340 reach
341}
342
343pub fn semantics_reach_of_chain(chain: &ModifierNodeChain) -> cranpose_foundation::SemanticsReach {
346 let mut reach = cranpose_foundation::SemanticsReach::default();
347 if !chain.has_capability(NodeCapabilities::SEMANTICS) {
348 return reach;
349 }
350 chain.for_each_node_with_capability(NodeCapabilities::SEMANTICS, |_ref, node| {
351 reach = reach.union(reach_of_node(node));
352 });
353 reach
354}
355
356pub fn collect_semantics_from_modifier(modifier: &Modifier) -> Option<SemanticsConfiguration> {
358 let mut handle = ModifierChainHandle::new();
359 handle.update(modifier);
360 collect_semantics_from_chain(handle.chain())
361}