fyrox_ui/inspector/editors/
inherit.rs1use crate::button::Button;
25use crate::{
26 button::{ButtonBuilder, ButtonMessage},
27 core::{
28 pool::Handle, reflect::prelude::*, reflect::FieldValue, type_traits::prelude::*,
29 uuid_provider, variable::InheritableVariable, visitor::prelude::*, PhantomDataSendSync,
30 },
31 grid::{Column, GridBuilder, Row},
32 image::ImageBuilder,
33 inspector::{
34 editors::{
35 PropertyEditorBuildContext, PropertyEditorDefinition, PropertyEditorInstance,
36 PropertyEditorMessageContext, PropertyEditorTranslationContext,
37 },
38 FieldKind, InheritableAction, InspectorError, PropertyChanged,
39 },
40 message::{MessageData, UiMessage},
41 resources::REVERT_ICON,
42 style::{resource::StyleResourceExt, Style},
43 utils::make_simple_tooltip,
44 widget::WidgetBuilder,
45 BuildContext, Control, MessageDirection, Thickness, UiNode, UserInterface, VerticalAlignment,
46 Widget, WidgetMessage,
47};
48use fyrox_graph::SceneGraph;
49use std::{
50 any::TypeId,
51 fmt::{Debug, Formatter},
52 ops::{Deref, DerefMut},
53};
54
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub enum InheritablePropertyEditorMessage {
57 Revert,
58 Modified(bool),
59}
60impl MessageData for InheritablePropertyEditorMessage {}
61
62#[derive(Debug, Clone, Visit, Reflect, ComponentProvider)]
63#[reflect(derived_type = "UiNode")]
64pub struct InheritablePropertyEditor {
65 widget: Widget,
66 revert: Handle<Button>,
67 inner_editor: Handle<UiNode>,
68}
69
70impl Deref for InheritablePropertyEditor {
71 type Target = Widget;
72
73 fn deref(&self) -> &Self::Target {
74 &self.widget
75 }
76}
77
78impl DerefMut for InheritablePropertyEditor {
79 fn deref_mut(&mut self) -> &mut Self::Target {
80 &mut self.widget
81 }
82}
83
84uuid_provider!(InheritablePropertyEditor = "d5dce72c-a54b-4754-96a3-2e923eaa802f");
85
86impl Control for InheritablePropertyEditor {
87 fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
88 self.widget.handle_routed_message(ui, message);
89
90 if let Some(ButtonMessage::Click) = message.data_from(self.revert) {
91 ui.post(self.handle, InheritablePropertyEditorMessage::Revert);
92 } else if let Some(InheritablePropertyEditorMessage::Modified(modified)) = message.data() {
93 if message.destination() == self.handle {
94 ui.send(self.revert, WidgetMessage::Visibility(*modified));
95 }
96 }
97
98 if message.destination() == self.inner_editor
104 && message.direction == MessageDirection::FromWidget
105 {
106 let mut clone = message.clone();
107 clone.destination = self.handle;
108 ui.send_message(clone);
109 }
110 }
111}
112
113struct InheritablePropertyEditorBuilder {
114 widget_builder: WidgetBuilder,
115 inner_editor: Handle<UiNode>,
116 container: Handle<UiNode>,
117 modified: bool,
118}
119
120impl InheritablePropertyEditorBuilder {
121 pub fn new(widget_builder: WidgetBuilder) -> Self {
122 Self {
123 widget_builder,
124 inner_editor: Handle::NONE,
125 container: Handle::NONE,
126 modified: false,
127 }
128 }
129
130 pub fn with_inner_editor(mut self, inner_editor: Handle<UiNode>) -> Self {
131 self.inner_editor = inner_editor;
132 self
133 }
134
135 pub fn with_container(mut self, container: Handle<UiNode>) -> Self {
136 self.container = container;
137 self
138 }
139
140 pub fn with_modified(mut self, modified: bool) -> Self {
141 self.modified = modified;
142 self
143 }
144
145 pub fn build(self, ctx: &mut BuildContext) -> Handle<InheritablePropertyEditor> {
146 let revert;
147 let grid = GridBuilder::new(WidgetBuilder::new().with_child(self.container).with_child({
148 revert = ButtonBuilder::new(
149 WidgetBuilder::new()
150 .with_visibility(self.modified)
151 .with_width(20.0)
152 .with_height(20.0)
153 .with_vertical_alignment(VerticalAlignment::Top)
154 .with_tooltip(make_simple_tooltip(ctx, "Revert To Parent"))
155 .with_margin(Thickness::uniform(1.0))
156 .on_column(1),
157 )
158 .with_content(
159 ImageBuilder::new(
160 WidgetBuilder::new()
161 .with_background(ctx.style.property(Style::BRUSH_BRIGHTEST))
162 .with_margin(Thickness::uniform(1.0))
163 .with_width(16.0)
164 .with_height(16.0),
165 )
166 .with_opt_texture(REVERT_ICON.clone())
167 .build(ctx),
168 )
169 .build(ctx);
170 revert
171 }))
172 .add_row(Row::auto())
173 .add_column(Column::stretch())
174 .add_column(Column::auto())
175 .build(ctx);
176
177 ctx.add(InheritablePropertyEditor {
178 widget: self.widget_builder.with_child(grid).build(ctx),
179 revert,
180 inner_editor: self.inner_editor,
181 })
182 }
183}
184
185pub struct InheritablePropertyEditorDefinition<T>
186where
187 T: FieldValue,
188{
189 #[allow(dead_code)]
190 phantom: PhantomDataSendSync<T>,
191}
192
193impl<T> InheritablePropertyEditorDefinition<T>
194where
195 T: FieldValue,
196{
197 pub fn new() -> Self {
198 Self {
199 phantom: Default::default(),
200 }
201 }
202}
203
204impl<T> Debug for InheritablePropertyEditorDefinition<T>
205where
206 T: Reflect + FieldValue,
207{
208 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
209 writeln!(f, "InheritablePropertyEditorDefinition")
210 }
211}
212
213impl<T> PropertyEditorDefinition for InheritablePropertyEditorDefinition<T>
214where
215 T: Reflect + FieldValue,
216{
217 fn value_type_id(&self) -> TypeId {
218 TypeId::of::<InheritableVariable<T>>()
219 }
220
221 fn create_instance(
222 &self,
223 ctx: PropertyEditorBuildContext,
224 ) -> Result<PropertyEditorInstance, InspectorError> {
225 if let Some(definition) = ctx
226 .definition_container
227 .definitions()
228 .get(&TypeId::of::<T>())
229 {
230 let property_info = ctx.property_info;
231
232 let value = property_info.cast_value::<InheritableVariable<T>>()?;
233
234 let proxy_property_info = FieldRef {
235 metadata: &FieldMetadata {
236 name: property_info.name,
237 display_name: property_info.display_name,
238 read_only: property_info.read_only,
239 immutable_collection: property_info.immutable_collection,
240 min_value: property_info.min_value,
241 max_value: property_info.max_value,
242 step: property_info.step,
243 precision: property_info.precision,
244 tag: property_info.tag,
245 doc: property_info.doc,
246 },
247 value: &**value,
248 };
249
250 let instance =
251 definition
252 .property_editor
253 .create_instance(PropertyEditorBuildContext {
254 build_context: ctx.build_context,
255 property_info: &proxy_property_info,
256 environment: ctx.environment.clone(),
257 definition_container: ctx.definition_container.clone(),
258 layer_index: ctx.layer_index,
259 generate_property_string_values: ctx.generate_property_string_values,
260 filter: ctx.filter,
261 name_column_width: ctx.name_column_width,
262 base_path: ctx.base_path.clone(),
263 has_parent_object: ctx.has_parent_object,
264 })?;
265
266 let wrapper = InheritablePropertyEditorBuilder::new(WidgetBuilder::new())
267 .with_container(match instance {
268 PropertyEditorInstance::Simple { editor } => editor,
269 PropertyEditorInstance::Custom { container, .. } => container,
270 })
271 .with_inner_editor(match instance {
272 PropertyEditorInstance::Simple { editor } => editor,
273 PropertyEditorInstance::Custom { editor, .. } => editor,
274 })
275 .with_modified(
276 ctx.has_parent_object
277 && ctx
278 .property_info
279 .cast_value::<InheritableVariable<T>>()?
280 .is_modified(),
281 )
282 .build(ctx.build_context)
283 .to_base();
284
285 Ok(match instance {
286 PropertyEditorInstance::Simple { .. } => {
287 PropertyEditorInstance::Simple { editor: wrapper }
288 }
289 PropertyEditorInstance::Custom { .. } => PropertyEditorInstance::Custom {
290 container: wrapper,
291 editor: wrapper,
292 },
293 })
294 } else {
295 Err(InspectorError::Custom("No editor!".to_string()))
296 }
297 }
298
299 fn create_message(
300 &self,
301 ctx: PropertyEditorMessageContext,
302 ) -> Result<Option<UiMessage>, InspectorError> {
303 if let Some(definition) = ctx
304 .definition_container
305 .definitions()
306 .get(&TypeId::of::<T>())
307 {
308 let instance = ctx
309 .ui
310 .node(ctx.instance)
311 .cast::<InheritablePropertyEditor>()
312 .unwrap();
313
314 let is_modified = ctx.has_parent_object
315 && ctx
316 .property_info
317 .cast_value::<InheritableVariable<T>>()?
318 .is_modified();
319 ctx.ui.send_sync(
320 instance.handle,
321 InheritablePropertyEditorMessage::Modified(is_modified),
322 );
323
324 let property_info = ctx.property_info;
325
326 let value = property_info.cast_value::<InheritableVariable<T>>()?;
327
328 let proxy_property_info = FieldRef {
329 metadata: &FieldMetadata {
330 name: property_info.name,
331 display_name: property_info.display_name,
332 read_only: property_info.read_only,
333 immutable_collection: property_info.immutable_collection,
334 min_value: property_info.min_value,
335 max_value: property_info.max_value,
336 step: property_info.step,
337 precision: property_info.precision,
338 tag: property_info.tag,
339 doc: property_info.doc,
340 },
341 value: &**value,
342 };
343
344 return definition
345 .property_editor
346 .create_message(PropertyEditorMessageContext {
347 property_info: &proxy_property_info,
348 environment: ctx.environment.clone(),
349 definition_container: ctx.definition_container.clone(),
350 instance: instance.inner_editor,
351 layer_index: ctx.layer_index,
352 ui: ctx.ui,
353 generate_property_string_values: ctx.generate_property_string_values,
354 filter: ctx.filter,
355 name_column_width: ctx.name_column_width,
356 base_path: ctx.base_path.clone(),
357 has_parent_object: ctx.has_parent_object,
358 });
359 }
360
361 Err(InspectorError::Custom("No editor!".to_string()))
362 }
363
364 fn translate_message(&self, ctx: PropertyEditorTranslationContext) -> Option<PropertyChanged> {
365 if let Some(InheritablePropertyEditorMessage::Revert) = ctx.message.data() {
366 return Some(PropertyChanged {
367 name: ctx.name.to_string(),
368 value: FieldKind::Inheritable(InheritableAction::Revert),
369 });
370 }
371
372 if let Some(definition) = ctx
374 .definition_container
375 .definitions()
376 .get(&TypeId::of::<T>())
377 {
378 return definition.property_editor.translate_message(
379 PropertyEditorTranslationContext {
380 environment: ctx.environment.clone(),
381 name: ctx.name,
382 message: ctx.message,
383 definition_container: ctx.definition_container.clone(),
384 },
385 );
386 }
387
388 None
389 }
390}