cranpose_ui/modifier/
semantics.rs1use std::cell::Cell;
2use std::fmt;
3use std::hash::{Hash, Hasher};
4use std::rc::Rc;
5
6use cranpose_core::NodeId;
7use cranpose_foundation::{
8 DelegatableNode, ModifierNode, ModifierNodeChain, ModifierNodeContext, ModifierNodeElement,
9 NodeCapabilities, NodeState, SemanticsConfiguration, SemanticsNode as SemanticsNodeTrait,
10};
11
12use super::{Modifier, ModifierChainHandle};
13use crate::render_state::AppContextId;
14
15#[derive(Clone, Default)]
47pub struct SemanticsRequester {
48 binding: Rc<Cell<Option<SemanticsBinding>>>,
57}
58
59#[derive(Clone, Copy)]
60struct SemanticsBinding {
61 app_context: AppContextId,
62 node_id: NodeId,
63}
64
65impl SemanticsRequester {
66 pub fn new() -> Self {
67 Self::default()
68 }
69
70 pub fn invalidate(&self) {
76 if let Some(binding) = self.binding.get() {
77 crate::semantics_dispatch::schedule_semantics_invalidation_in(
78 binding.app_context,
79 binding.node_id,
80 );
81 }
82 }
83
84 pub fn node_id(&self) -> Option<NodeId> {
86 self.binding.get().map(|binding| binding.node_id)
87 }
88
89 fn bind(&self, binding: Option<SemanticsBinding>) {
90 self.binding.set(binding);
91 }
92
93 fn binding_here(node_id: Option<NodeId>) -> Option<SemanticsBinding> {
98 Some(SemanticsBinding {
99 app_context: crate::render_state::current_app_context_id_opt()?,
100 node_id: node_id?,
101 })
102 }
103}
104
105impl fmt::Debug for SemanticsRequester {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 f.debug_struct("SemanticsRequester")
108 .field("node_id", &self.node_id())
109 .finish()
110 }
111}
112
113pub struct SemanticsModifierNode {
114 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
115 state: NodeState,
116}
117
118impl SemanticsModifierNode {
119 pub fn new(recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>) -> Self {
120 Self {
121 recorder,
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 struct SemanticsRequesterNode {
149 state: NodeState,
150 requester: SemanticsRequester,
151}
152
153impl SemanticsRequesterNode {
154 pub(crate) fn new(requester: SemanticsRequester) -> Self {
155 Self {
156 state: NodeState::new(),
157 requester,
158 }
159 }
160}
161
162impl DelegatableNode for SemanticsRequesterNode {
163 fn node_state(&self) -> &NodeState {
164 &self.state
165 }
166}
167
168impl ModifierNode for SemanticsRequesterNode {
169 fn on_attach(&mut self, context: &mut dyn ModifierNodeContext) {
170 self.state.set_attached(true);
171 self.requester
172 .bind(SemanticsRequester::binding_here(context.node_id()));
173 }
174
175 fn on_detach(&mut self) {
176 self.state.set_attached(false);
177 self.requester.bind(None);
180 }
181}
182
183#[derive(Clone)]
185pub struct SemanticsRequesterElement {
186 requester: SemanticsRequester,
187}
188
189impl SemanticsRequesterElement {
190 pub(crate) fn new(requester: SemanticsRequester) -> Self {
191 Self { requester }
192 }
193}
194
195impl fmt::Debug for SemanticsRequesterElement {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 f.write_str("SemanticsRequesterElement")
198 }
199}
200
201impl PartialEq for SemanticsRequesterElement {
202 fn eq(&self, other: &Self) -> bool {
203 Rc::ptr_eq(&self.requester.binding, &other.requester.binding)
204 }
205}
206
207impl Eq for SemanticsRequesterElement {}
208
209impl Hash for SemanticsRequesterElement {
210 fn hash<H: Hasher>(&self, state: &mut H) {
211 Rc::as_ptr(&self.requester.binding).hash(state);
212 }
213}
214
215impl ModifierNodeElement for SemanticsRequesterElement {
216 type Node = SemanticsRequesterNode;
217
218 fn create(&self) -> Self::Node {
219 SemanticsRequesterNode::new(self.requester.clone())
220 }
221
222 fn update(&self, node: &mut Self::Node) {
223 if !Rc::ptr_eq(&node.requester.binding, &self.requester.binding) {
227 let bound = node.requester.binding.get();
228 node.requester.bind(None);
229 node.requester = self.requester.clone();
230 node.requester.bind(bound);
231 }
232 }
233
234 fn inspector_name(&self) -> &'static str {
235 "semanticsRequester"
236 }
237
238 fn capabilities(&self) -> NodeCapabilities {
239 NodeCapabilities::NONE
240 }
241}
242
243impl SemanticsNodeTrait for SemanticsModifierNode {
244 fn merge_semantics(&self, config: &mut SemanticsConfiguration) {
245 (self.recorder)(config);
246 }
247}
248
249#[derive(Clone)]
250pub struct SemanticsElement {
251 recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>,
252}
253
254impl SemanticsElement {
255 pub fn new(recorder: Rc<dyn Fn(&mut SemanticsConfiguration)>) -> Self {
258 Self { recorder }
259 }
260}
261
262impl fmt::Debug for SemanticsElement {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264 f.write_str("SemanticsElement")
265 }
266}
267
268impl PartialEq for SemanticsElement {
269 fn eq(&self, _other: &Self) -> bool {
270 true
274 }
275}
276
277impl Eq for SemanticsElement {}
278
279impl Hash for SemanticsElement {
280 fn hash<H: Hasher>(&self, state: &mut H) {
281 "semantics".hash(state);
283 }
284}
285
286impl ModifierNodeElement for SemanticsElement {
287 type Node = SemanticsModifierNode;
288
289 fn create(&self) -> Self::Node {
290 SemanticsModifierNode::new(self.recorder.clone())
291 }
292
293 fn update(&self, node: &mut Self::Node) {
294 node.recorder = self.recorder.clone();
295 }
296
297 fn capabilities(&self) -> NodeCapabilities {
298 NodeCapabilities::SEMANTICS
299 }
300
301 fn always_update(&self) -> bool {
302 true
304 }
305}
306
307fn merge_semantics_from_node(node: &dyn ModifierNode, config: &mut SemanticsConfiguration) -> bool {
308 let mut merged = false;
309
310 if let Some(semantics) = node.as_semantics_node() {
311 semantics.merge_semantics(config);
312 merged = true;
313 }
314
315 node.for_each_delegate(&mut |delegate| {
316 if merge_semantics_from_node(delegate, config) {
317 merged = true;
318 }
319 });
320
321 merged
322}
323
324pub fn collect_semantics_from_chain(chain: &ModifierNodeChain) -> Option<SemanticsConfiguration> {
326 if !chain.has_capability(NodeCapabilities::SEMANTICS) {
327 return None;
328 }
329
330 let mut config = SemanticsConfiguration::default();
331 let mut merged = false;
332 chain.for_each_node_with_capability(NodeCapabilities::SEMANTICS, |_ref, node| {
333 if merge_semantics_from_node(node, &mut config) {
334 merged = true;
335 }
336 });
337
338 if merged {
339 Some(config)
340 } else {
341 None
342 }
343}
344
345pub fn collect_semantics_from_modifier(modifier: &Modifier) -> Option<SemanticsConfiguration> {
347 let mut handle = ModifierChainHandle::new();
348 handle.update(modifier);
349 collect_semantics_from_chain(handle.chain())
350}