Skip to main content

fyrox_ui/node/
container.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! A wrapper for node pool record that allows to define custom visit method to have full
22//! control over instantiation process at deserialization.
23
24use crate::{
25    constructor::WidgetConstructorContainer,
26    core::{
27        pool::PayloadContainer,
28        reflect::prelude::*,
29        uuid::Uuid,
30        visitor::{Visit, VisitResult, Visitor},
31    },
32    UiNode,
33};
34use fyrox_core::visitor::error::VisitError;
35
36/// A wrapper for widget pool record that allows to define custom visit method to have full
37/// control over instantiation process at deserialization.
38#[derive(Debug, Clone, Default, Reflect)]
39pub struct WidgetContainer(Option<UiNode>);
40
41fn read_widget(name: &str, visitor: &mut Visitor) -> Result<UiNode, VisitError> {
42    let mut region = visitor.enter_region(name)?;
43
44    let mut id = Uuid::default();
45    id.visit("TypeUuid", &mut region)?;
46
47    let serialization_context = region
48        .blackboard
49        .get::<WidgetConstructorContainer>()
50        .expect("Visitor environment must contain serialization context!");
51
52    let mut widget = serialization_context
53        .try_create(&id)
54        .ok_or_else(|| panic!("Unknown widget type uuid {id}!"))
55        .unwrap();
56
57    widget.visit("WidgetData", &mut region)?;
58
59    Ok(widget)
60}
61
62fn write_widget(name: &str, widget: &mut UiNode, visitor: &mut Visitor) -> VisitResult {
63    let mut region = visitor.enter_region(name)?;
64
65    let mut id = widget.id();
66    id.visit("TypeUuid", &mut region)?;
67
68    widget.visit("WidgetData", &mut region)?;
69
70    Ok(())
71}
72
73impl Visit for WidgetContainer {
74    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
75        let mut region = visitor.enter_region(name)?;
76
77        let mut is_some = u8::from(self.is_some());
78        is_some.visit("IsSome", &mut region)?;
79
80        if is_some != 0 {
81            if region.is_reading() {
82                *self = WidgetContainer(Some(read_widget("Data", &mut region)?));
83            } else {
84                write_widget("Data", self.0.as_mut().unwrap(), &mut region)?;
85            }
86        }
87
88        Ok(())
89    }
90}
91
92impl PayloadContainer for WidgetContainer {
93    type Element = UiNode;
94
95    fn new_empty() -> Self {
96        Self(None)
97    }
98
99    fn new(element: Self::Element) -> Self {
100        Self(Some(element))
101    }
102
103    fn is_some(&self) -> bool {
104        self.0.is_some()
105    }
106
107    fn as_ref(&self) -> Option<&Self::Element> {
108        self.0.as_ref()
109    }
110
111    fn as_mut(&mut self) -> Option<&mut Self::Element> {
112        self.0.as_mut()
113    }
114
115    fn replace(&mut self, element: Self::Element) -> Option<Self::Element> {
116        self.0.replace(element)
117    }
118
119    fn take(&mut self) -> Option<Self::Element> {
120        self.0.take()
121    }
122}