fyrox_ui/inspector/editors/
inspectable.rs1use crate::inspector::InspectorContextArgs;
24use crate::{
25 core::reflect::prelude::*,
26 inspector::{
27 editors::{
28 PropertyEditorBuildContext, PropertyEditorDefinition, PropertyEditorInstance,
29 PropertyEditorMessageContext, PropertyEditorTranslationContext,
30 },
31 make_expander_container, FieldAction, Inspector, InspectorBuilder, InspectorContext,
32 InspectorError, InspectorMessage, PropertyChanged,
33 },
34 message::{MessageDirection, UiMessage},
35 widget::WidgetBuilder,
36 UiNode,
37};
38use fyrox_core::pool::Handle;
39use fyrox_core::PhantomDataSendSync;
40use fyrox_graph::SceneGraph;
41use std::{
42 any::TypeId,
43 fmt::{Debug, Formatter},
44};
45
46pub struct InspectablePropertyEditorDefinition<T>
52where
53 T: Reflect,
54{
55 #[allow(dead_code)]
56 phantom: PhantomDataSendSync<T>,
57}
58
59impl<T> InspectablePropertyEditorDefinition<T>
60where
61 T: Reflect,
62{
63 pub fn new() -> Self {
64 Self {
65 phantom: Default::default(),
66 }
67 }
68}
69
70impl<T> Debug for InspectablePropertyEditorDefinition<T>
71where
72 T: Reflect,
73{
74 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
75 writeln!(f, "InspectablePropertyEditorDefinition")
76 }
77}
78
79impl<T> PropertyEditorDefinition for InspectablePropertyEditorDefinition<T>
80where
81 T: Reflect,
82{
83 fn value_type_id(&self) -> TypeId {
84 TypeId::of::<T>()
85 }
86
87 fn create_instance(
88 &self,
89 ctx: PropertyEditorBuildContext,
90 ) -> Result<PropertyEditorInstance, InspectorError> {
91 let value = ctx.property_info.cast_value::<T>()?;
92
93 let inspector_context = InspectorContext::from_object(InspectorContextArgs {
94 object: value,
95 ctx: ctx.build_context,
96 definition_container: ctx.definition_container.clone(),
97 environment: ctx.environment.clone(),
98 layer_index: ctx.layer_index + 1,
99 generate_property_string_values: ctx.generate_property_string_values,
100 filter: ctx.filter,
101 name_column_width: ctx.name_column_width,
102 base_path: ctx.base_path.clone(),
103 has_parent_object: ctx.has_parent_object,
104 });
105
106 let editor;
107 let container = make_expander_container(
108 ctx.layer_index,
109 ctx.property_info.display_name,
110 ctx.property_info.doc,
111 Handle::<UiNode>::NONE,
112 {
113 editor = InspectorBuilder::new(WidgetBuilder::new())
114 .with_context(inspector_context)
115 .build(ctx.build_context)
116 .to_base();
117 editor
118 },
119 ctx.name_column_width,
120 ctx.build_context,
121 );
122
123 Ok(PropertyEditorInstance::Custom { container, editor })
124 }
125
126 fn create_message(
130 &self,
131 ctx: PropertyEditorMessageContext,
132 ) -> Result<Option<UiMessage>, InspectorError> {
133 let value = ctx.property_info.cast_value::<T>()?;
134
135 let mut error_group = Vec::new();
136
137 let inspector_context = ctx
138 .ui
139 .node(ctx.instance)
140 .cast::<Inspector>()
141 .expect("Must be Inspector!")
142 .context()
143 .clone();
144 if let Err(e) = inspector_context.sync(
145 value,
146 ctx.ui,
147 ctx.layer_index + 1,
148 ctx.generate_property_string_values,
149 ctx.filter,
150 ctx.base_path.clone(),
151 ) {
152 error_group.extend(e)
153 }
154
155 if error_group.is_empty() {
156 Ok(None)
157 } else {
158 Err(InspectorError::Group(error_group))
159 }
160 }
161
162 fn translate_message(&self, ctx: PropertyEditorTranslationContext) -> Option<PropertyChanged> {
163 if let Some(InspectorMessage::PropertyChanged(msg)) = ctx.message.data::<InspectorMessage>()
164 {
165 if ctx.message.direction() == MessageDirection::FromWidget {
166 return Some(PropertyChanged {
167 name: ctx.name.to_owned(),
168
169 action: FieldAction::InspectableAction(Box::new(msg.clone())),
170 });
171 }
172 }
173
174 None
175 }
176}