fyrox_ui/node/
container.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! A wrapper for node pool record that allows to define custom visit method to have full
//! control over instantiation process at deserialization.

use crate::{
    constructor::WidgetConstructorContainer,
    core::{
        pool::PayloadContainer,
        reflect::prelude::*,
        uuid::Uuid,
        visitor::{Visit, VisitError, VisitResult, Visitor},
    },
    UiNode,
};

/// A wrapper for widget pool record that allows to define custom visit method to have full
/// control over instantiation process at deserialization.
#[derive(Debug, Default, Reflect)]
pub struct WidgetContainer(Option<UiNode>);

fn read_widget(name: &str, visitor: &mut Visitor) -> Result<UiNode, VisitError> {
    let mut region = visitor.enter_region(name)?;

    let mut id = Uuid::default();
    id.visit("TypeUuid", &mut region)?;

    let serialization_context = region
        .blackboard
        .get::<WidgetConstructorContainer>()
        .expect("Visitor environment must contain serialization context!");

    let mut widget = serialization_context
        .try_create(&id)
        .ok_or_else(|| panic!("Unknown widget type uuid {}!", id))
        .unwrap();

    widget.visit("WidgetData", &mut region)?;

    Ok(widget)
}

fn write_widget(name: &str, widget: &mut UiNode, visitor: &mut Visitor) -> VisitResult {
    let mut region = visitor.enter_region(name)?;

    let mut id = widget.id();
    id.visit("TypeUuid", &mut region)?;

    widget.visit("WidgetData", &mut region)?;

    Ok(())
}

impl Visit for WidgetContainer {
    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
        let mut region = visitor.enter_region(name)?;

        let mut is_some = u8::from(self.is_some());
        is_some.visit("IsSome", &mut region)?;

        if is_some != 0 {
            if region.is_reading() {
                *self = WidgetContainer(Some(read_widget("Data", &mut region)?));
            } else {
                write_widget("Data", self.0.as_mut().unwrap(), &mut region)?;
            }
        }

        Ok(())
    }
}

impl PayloadContainer for WidgetContainer {
    type Element = UiNode;

    fn new_empty() -> Self {
        Self(None)
    }

    fn new(element: Self::Element) -> Self {
        Self(Some(element))
    }

    fn is_some(&self) -> bool {
        self.0.is_some()
    }

    fn as_ref(&self) -> Option<&Self::Element> {
        self.0.as_ref()
    }

    fn as_mut(&mut self) -> Option<&mut Self::Element> {
        self.0.as_mut()
    }

    fn replace(&mut self, element: Self::Element) -> Option<Self::Element> {
        self.0.replace(element)
    }

    fn take(&mut self) -> Option<Self::Element> {
        self.0.take()
    }
}