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