cranpose_ui/modifier/
layout_data.rs1use std::{
2 hash::{Hash, Hasher},
3 rc::Rc,
4};
5
6use cranpose_foundation::{
7 DelegatableNode, InvalidationKind, ModifierNode, ModifierNodeContext, ModifierNodeElement,
8 NodeCapabilities, NodeState,
9};
10use cranpose_ui_layout::LayoutData;
11
12use super::{Modifier, inspector_metadata};
13
14impl Modifier {
15 pub fn layout_data(self, data: impl LayoutData) -> Self {
19 let data: Rc<dyn LayoutData> = Rc::new(data);
20 let inspected = Rc::clone(&data);
21 let modifier = Self::with_element(LayoutDataElement { data }).with_inspector_metadata(
22 inspector_metadata("layoutData", move |info| {
23 info.add_property("data", format!("{inspected:?}"));
24 }),
25 );
26 self.then(modifier)
27 }
28}
29
30#[derive(Debug)]
32pub(crate) struct LayoutDataNode {
33 data: Rc<dyn LayoutData>,
34 state: NodeState,
35}
36
37impl LayoutDataNode {
38 pub(crate) fn data(&self) -> &Rc<dyn LayoutData> {
39 &self.data
40 }
41}
42
43impl DelegatableNode for LayoutDataNode {
44 fn node_state(&self) -> &NodeState {
45 &self.state
46 }
47}
48
49impl ModifierNode for LayoutDataNode {
50 fn on_attach(&mut self, context: &mut dyn ModifierNodeContext) {
51 context.invalidate(InvalidationKind::Layout);
52 }
53}
54
55#[derive(Debug)]
56struct LayoutDataElement {
57 data: Rc<dyn LayoutData>,
58}
59
60impl PartialEq for LayoutDataElement {
61 fn eq(&self, other: &Self) -> bool {
62 self.data.same_as(&*other.data)
63 }
64}
65
66impl Hash for LayoutDataElement {
67 fn hash<H: Hasher>(&self, state: &mut H) {
69 self.data.as_any().type_id().hash(state);
70 }
71}
72
73impl ModifierNodeElement for LayoutDataElement {
74 type Node = LayoutDataNode;
75
76 fn create(&self) -> Self::Node {
77 LayoutDataNode {
78 data: Rc::clone(&self.data),
79 state: NodeState::new(),
80 }
81 }
82
83 fn update(&self, node: &mut Self::Node) {
84 if !node.data.same_as(&*self.data) {
85 node.data = Rc::clone(&self.data);
86 }
87 }
88
89 fn capabilities(&self) -> NodeCapabilities {
90 NodeCapabilities::LAYOUT
91 }
92}