fyrox_ui/inspector/editors/
refcell.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
21use crate::{
22    core::{reflect::prelude::*, reflect::FieldValue},
23    inspector::{
24        editors::{
25            PropertyEditorBuildContext, PropertyEditorDefinition, PropertyEditorInstance,
26            PropertyEditorMessageContext, PropertyEditorTranslationContext,
27        },
28        InspectorError, PropertyChanged,
29    },
30    message::UiMessage,
31};
32use fyrox_core::PhantomDataSendSync;
33use std::{
34    any::TypeId,
35    cell::RefCell,
36    fmt::{Debug, Formatter},
37};
38
39pub struct RefCellPropertyEditorDefinition<T>
40where
41    T: FieldValue,
42{
43    #[allow(dead_code)]
44    phantom: PhantomDataSendSync<T>,
45}
46
47impl<T> RefCellPropertyEditorDefinition<T>
48where
49    T: FieldValue,
50{
51    pub fn new() -> Self {
52        Self {
53            phantom: Default::default(),
54        }
55    }
56}
57
58impl<T> Debug for RefCellPropertyEditorDefinition<T>
59where
60    T: Reflect + FieldValue,
61{
62    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
63        writeln!(f, "RefCellPropertyEditorDefinition")
64    }
65}
66
67fn make_proxy<'a, 'b, 'c, T>(
68    value: &'a T,
69    property_info: &'b FieldInfo<'a, 'c>,
70) -> Result<FieldInfo<'a, 'c>, InspectorError>
71where
72    T: Reflect + FieldValue,
73    'b: 'a,
74{
75    Ok(FieldInfo {
76        owner_type_id: TypeId::of::<T>(),
77        name: property_info.name,
78        display_name: property_info.display_name,
79        value,
80        reflect_value: value,
81        read_only: property_info.read_only,
82        immutable_collection: property_info.immutable_collection,
83        min_value: property_info.min_value,
84        max_value: property_info.max_value,
85        step: property_info.step,
86        precision: property_info.precision,
87        description: property_info.description,
88        tag: property_info.tag,
89        type_name: property_info.type_name,
90        doc: property_info.doc,
91    })
92}
93
94impl<T> PropertyEditorDefinition for RefCellPropertyEditorDefinition<T>
95where
96    T: Reflect + FieldValue,
97{
98    fn value_type_id(&self) -> TypeId {
99        TypeId::of::<RefCell<T>>()
100    }
101
102    fn create_instance(
103        &self,
104        ctx: PropertyEditorBuildContext,
105    ) -> Result<PropertyEditorInstance, InspectorError> {
106        if let Some(definition) = ctx
107            .definition_container
108            .definitions()
109            .get(&TypeId::of::<T>())
110        {
111            let value = ctx.property_info.cast_value::<RefCell<T>>()?.borrow();
112            definition
113                .property_editor
114                .create_instance(PropertyEditorBuildContext {
115                    build_context: ctx.build_context,
116                    property_info: &make_proxy::<T>(&value, ctx.property_info)?,
117                    environment: ctx.environment.clone(),
118                    definition_container: ctx.definition_container.clone(),
119                    sync_flag: ctx.sync_flag,
120                    layer_index: ctx.layer_index,
121                    generate_property_string_values: ctx.generate_property_string_values,
122                    filter: ctx.filter,
123                    name_column_width: ctx.name_column_width,
124                })
125        } else {
126            Err(InspectorError::Custom("No editor!".to_string()))
127        }
128    }
129
130    fn create_message(
131        &self,
132        ctx: PropertyEditorMessageContext,
133    ) -> Result<Option<UiMessage>, InspectorError> {
134        if let Some(definition) = ctx
135            .definition_container
136            .definitions()
137            .get(&TypeId::of::<T>())
138        {
139            let value = ctx.property_info.cast_value::<RefCell<T>>()?.borrow();
140            return definition
141                .property_editor
142                .create_message(PropertyEditorMessageContext {
143                    property_info: &make_proxy::<T>(&value, ctx.property_info)?,
144                    environment: ctx.environment.clone(),
145                    definition_container: ctx.definition_container.clone(),
146                    sync_flag: ctx.sync_flag,
147                    instance: ctx.instance,
148                    layer_index: ctx.layer_index,
149                    ui: ctx.ui,
150                    generate_property_string_values: ctx.generate_property_string_values,
151                    filter: ctx.filter,
152                    name_column_width: ctx.name_column_width,
153                });
154        }
155
156        Err(InspectorError::Custom("No editor!".to_string()))
157    }
158
159    fn translate_message(&self, ctx: PropertyEditorTranslationContext) -> Option<PropertyChanged> {
160        // Try translate other messages using inner property editor.
161        if let Some(definition) = ctx
162            .definition_container
163            .definitions()
164            .get(&TypeId::of::<T>())
165        {
166            return definition.property_editor.translate_message(
167                PropertyEditorTranslationContext {
168                    environment: ctx.environment.clone(),
169                    name: ctx.name,
170                    owner_type_id: ctx.owner_type_id,
171                    message: ctx.message,
172                    definition_container: ctx.definition_container.clone(),
173                },
174            );
175        }
176
177        None
178    }
179}