fyrox_ui/inspector/editors/
mod.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 collection of [PropertyEditorDefinition] objects for a wide variety of types,
22//! including standard Rust types and Fyrox core types.
23
24use crate::inspector::editors::texture_slice::TextureSlicePropertyEditorDefinition;
25use crate::{
26    absm::{EventAction, EventKind},
27    bit::BitField,
28    border::Border,
29    brush::{Brush, GradientPoint},
30    button::Button,
31    canvas::Canvas,
32    core::{
33        algebra::{UnitQuaternion, Vector2, Vector3, Vector4},
34        color::Color,
35        color_gradient::ColorGradient,
36        math::{curve::Curve, Rect, SmoothAngle},
37        parking_lot::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard},
38        pool::Handle,
39        reflect::{FieldInfo, FieldValue, Reflect},
40        sstorage::ImmutableString,
41        uuid::Uuid,
42        visitor::prelude::*,
43    },
44    decorator::Decorator,
45    dropdown_list::DropdownList,
46    expander::Expander,
47    formatted_text::{FormattedText, WrapMode},
48    grid::{Grid, GridDimension, SizeMode},
49    image::Image,
50    inspector::{
51        editors::{
52            array::ArrayPropertyEditorDefinition,
53            bool::BoolPropertyEditorDefinition,
54            collection::{CollectionItem, VecCollectionPropertyEditorDefinition},
55            color::{ColorGradientPropertyEditorDefinition, ColorPropertyEditorDefinition},
56            curve::CurvePropertyEditorDefinition,
57            enumeration::{EnumPropertyEditorDefinition, InspectableEnum},
58            immutable_string::ImmutableStringPropertyEditorDefinition,
59            inherit::InheritablePropertyEditorDefinition,
60            inspectable::InspectablePropertyEditorDefinition,
61            key::KeyBindingPropertyEditorDefinition,
62            matrix2::MatrixPropertyEditorDefinition,
63            numeric::NumericPropertyEditorDefinition,
64            path::PathPropertyEditorDefinition,
65            quat::QuatPropertyEditorDefinition,
66            range::RangePropertyEditorDefinition,
67            rect::RectPropertyEditorDefinition,
68            refcell::RefCellPropertyEditorDefinition,
69            string::StringPropertyEditorDefinition,
70            style::StyledPropertyEditorDefinition,
71            utf32::Utf32StringPropertyEditorDefinition,
72            uuid::UuidPropertyEditorDefinition,
73            vec::{
74                Vec2PropertyEditorDefinition, Vec3PropertyEditorDefinition,
75                Vec4PropertyEditorDefinition,
76            },
77        },
78        InspectorEnvironment, InspectorError, PropertyChanged, PropertyFilter,
79    },
80    key::{HotKeyEditor, KeyBinding, KeyBindingEditor},
81    list_view::{ListView, ListViewItem},
82    menu::{Menu, MenuItem},
83    message::{CursorIcon, UiMessage},
84    messagebox::MessageBox,
85    nine_patch::{NinePatch, StretchMode},
86    numeric::NumericUpDown,
87    path::PathEditor,
88    popup::Popup,
89    progress_bar::ProgressBar,
90    range::RangeEditor,
91    rect::RectEditor,
92    scroll_bar::ScrollBar,
93    scroll_panel::ScrollPanel,
94    stack_panel::StackPanel,
95    style::StyledProperty,
96    tab_control::TabControl,
97    text::Text,
98    text_box::{Position, SelectionRange, TextBox, TextCommitMode},
99    tree::{Tree, TreeRoot},
100    uuid::UuidEditor,
101    vec::VecEditor,
102    vector_image::{Primitive, VectorImage},
103    widget::Widget,
104    window::Window,
105    wrap_panel::WrapPanel,
106    BuildContext, HorizontalAlignment, Orientation, RcUiNodeHandle, RcUiNodeHandleInner, Thickness,
107    UiNode, UserInterface, VerticalAlignment,
108};
109use fxhash::FxHashMap;
110use fyrox_animation::machine::Parameter;
111use fyrox_texture::TextureResource;
112use std::{
113    any::{Any, TypeId},
114    cell::RefCell,
115    fmt::Debug,
116    fmt::Formatter,
117    ops::Range,
118    path::PathBuf,
119    str::FromStr,
120    sync::Arc,
121};
122use strum::VariantNames;
123
124pub mod array;
125pub mod bit;
126pub mod bool;
127pub mod collection;
128pub mod color;
129pub mod curve;
130pub mod enumeration;
131pub mod immutable_string;
132pub mod inherit;
133pub mod inspectable;
134pub mod key;
135pub mod matrix2;
136pub mod numeric;
137pub mod path;
138pub mod quat;
139pub mod range;
140pub mod rect;
141pub mod refcell;
142pub mod string;
143mod style;
144pub mod texture_slice;
145pub mod utf32;
146pub mod uuid;
147pub mod vec;
148
149/// This structure is passed to [PropertyEditorDefinition::create_instance] in order to allow it to
150/// build a widget to allow a property to be edited.
151pub struct PropertyEditorBuildContext<'a, 'b, 'c, 'd> {
152    /// General context for widget building to be used for creating the editor.
153    pub build_context: &'a mut BuildContext<'c>,
154    /// The FieldInfo of the property to edit, extracted from the object we are inspecting by reflection.
155    pub property_info: &'b FieldInfo<'b, 'd>,
156    /// Untyped reference to the environment that the Inspector is being used in.
157    /// This will often be
158    /// [fyroxed_base::inspector::EditorEnvironment](https://docs.rs/fyroxed_base/latest/fyroxed_base/inspector/struct.EditorEnvironment.html)
159    /// when the Inspector is being used in Fyroxed, but Inspector widgets can be used in other applications,
160    /// and we can access those applications by casting the environment to the appropriate type.
161    pub environment: Option<Arc<dyn InspectorEnvironment>>,
162    /// The list of the Inspectors property editors.
163    /// This allows one property editor to make use of other property editors.
164    pub definition_container: Arc<PropertyEditorDefinitionContainer>,
165    /// Controls the flags that are included with messages through the [UiMessage::flags] property.
166    /// This is used to distinguish sync messages from other messages and is handled automatically by
167    /// [InspectorContext](crate::inspector::InspectorContext).
168    pub sync_flag: u64,
169    /// Editors can be nested within other editors, such as when an array
170    /// editor contains editors for each element of the array.
171    /// The layer_index indicates how deeply nested the editor widget we
172    /// are creating will be.
173    pub layer_index: usize,
174    /// When true, this indicates that an Inspector should generate strings from `format!("{:?}", field)`, for each field.
175    /// Having this in the property editor build context indicates how any Inspectors that are created as part of the new
176    /// editor should behave.
177    pub generate_property_string_values: bool,
178    /// Determines how properties should be filtered in any Inspectors created within the editor that is being built.
179    pub filter: PropertyFilter,
180    /// Width of the property name column.
181    pub name_column_width: f32,
182}
183
184/// This structure is passed to [PropertyEditorDefinition::create_message] in order to generate a message that will
185/// update the editor widget to the property's current value.
186pub struct PropertyEditorMessageContext<'a, 'b, 'c> {
187    /// Controls the flags that are included with messages through the [UiMessage::flags] property.
188    /// This is used to distinguish sync messages from other messages and is handled automatically by
189    /// [InspectorContext](crate::inspector::InspectorContext).
190    /// There is no need to put this flag into the message return by the create_message method.
191    pub sync_flag: u64,
192    /// The handle of widget that the message will be sent to. It should be an editor created by
193    /// [PropertyEditorDefinition::create_instance].
194    pub instance: Handle<UiNode>,
195    /// The UserInterface is provided to make it possible for `create_message` to send whatever messages
196    /// are needed directly instead of returning a message. In this case, the sent messages should have their
197    /// [UiMessage::flags] set to `sync_flag`.
198    pub ui: &'b mut UserInterface,
199    /// The FieldInfo of the property to edit, extracted from the object we are inspecting by reflection.
200    pub property_info: &'a FieldInfo<'a, 'c>,
201    /// The list of the Inspectors property editors.
202    /// This allows one property editor to make use of other property editors.
203    pub definition_container: Arc<PropertyEditorDefinitionContainer>,
204    /// Editors can be nested within other editors, such as when an array
205    /// editor contains editors for each element of the array.
206    /// The layer_index indicates the nesting level of the widget that will receive the created message.
207    pub layer_index: usize,
208    /// Optional untyped information about the broader application in which
209    /// this proprety is being translated. This allows the created message to
210    /// adapt to the situation if we can successfully cast the given
211    /// [InspectorEnvironment] into a specific type.
212    pub environment: Option<Arc<dyn InspectorEnvironment>>,
213    /// When true, this indicates that an Inspector should generate strings from `format!("{:?}", field)`, for each field.
214    /// Having this in the property editor build context indicates how any Inspectors that are update due to the created message
215    /// should behave.
216    pub generate_property_string_values: bool,
217    /// Determines how properties should be filtered in any Inspectors that are updated by the created message.
218    pub filter: PropertyFilter,
219    /// Width of the property name column.
220    pub name_column_width: f32,
221}
222
223/// The details relevant to translating a message from an editor widget into
224/// a [PropertyChanged] message that an [Inspector](crate::inspector::Inspector) widget
225/// can use to update the inspected property based on the messages from the editor.
226pub struct PropertyEditorTranslationContext<'b, 'c> {
227    /// Optional untyped information about the broader application in which
228    /// this proprety is being translated. This allows the translation to
229    /// adapt to the situation if we can successfully cast the given
230    /// [InspectorEnvironment] into a specific type.
231    ///
232    /// When the environment is not None, it is often an
233    /// [fyroxed_base::inspector::EditorEnvironment](https://docs.rs/fyroxed_base/latest/fyroxed_base/inspector/struct.EditorEnvironment.html)
234    /// which may be accessed using EditorEnvironment::try_get_from.
235    /// For example, the EditorEnvironment can be used by
236    /// [fyroxed_base::inspector::editors::script::ScriptPropertyEditor](https://docs.rs/fyroxed_base/latest/fyroxed_base/inspector/editors/script/struct.ScriptPropertyEditor.html)
237    /// to translate the UUID of a script into an actual
238    /// [fyrox::script::Script](https://docs.rs/fyrox/latest/fyrox/script/struct.Script.html)
239    /// when it receives a
240    /// [ScriptPropertyEditorMessage::Value](https://docs.rs/fyroxed_base/latest/fyroxed_base/inspector/editors/script/enum.ScriptPropertyEditorMessage.html#variant.Value).
241    pub environment: Option<Arc<dyn InspectorEnvironment>>,
242    /// The name of the property being edited.
243    /// This comes from [ContextEntry::property_name](crate::inspector::ContextEntry).
244    pub name: &'b str,
245    /// The type of the object whose property is being edited.
246    /// This comes from [ContextEntry::property_owner_type_id](crate::inspector::ContextEntry).
247    pub owner_type_id: TypeId,
248    /// The original message that may be translated, if it represents a change in the property.
249    pub message: &'c UiMessage,
250    /// The list of the Inspectors property editors.
251    /// This allows one property editor to make use of other property editors.
252    pub definition_container: Arc<PropertyEditorDefinitionContainer>,
253}
254
255/// A widget handle that is to act as an editor in an [Insector](crate::inspector::Inspector), with or without
256/// a custom container widget to show the name of the property that is being edited.
257#[derive(Clone, Debug, PartialEq, Visit, Reflect)]
258pub enum PropertyEditorInstance {
259    /// A property editor that is to be given a default container, which is just a label to the left
260    /// of the editor to show the name of the property being edited.
261    Simple {
262        /// A property editor. Could be any widget that capable of editing a property
263        /// value.
264        editor: Handle<UiNode>,
265    },
266    /// A property editor that comes with its own custom container.
267    Custom {
268        /// A widget that contains the editor.
269        /// It should include a label to identify the property being edited.
270        container: Handle<UiNode>,
271
272        /// A property editor. Could be any widget that capable of editing a property
273        /// value.
274        editor: Handle<UiNode>,
275    },
276}
277
278impl Default for PropertyEditorInstance {
279    fn default() -> Self {
280        Self::Simple {
281            editor: Default::default(),
282        }
283    }
284}
285
286impl PropertyEditorInstance {
287    pub fn editor(&self) -> Handle<UiNode> {
288        match self {
289            PropertyEditorInstance::Simple { editor }
290            | PropertyEditorInstance::Custom { editor, .. } => *editor,
291        }
292    }
293}
294
295/// The trait for all property editor definitions which are capable of providing
296/// and editor widget to an [Inspector](crate::inspector::Inspector) and helping
297/// the inspector handle the necessary messages to and from that widget.
298pub trait PropertyEditorDefinition: Debug + Send + Sync {
299    /// The type of property that the editor will edit.
300    fn value_type_id(&self) -> TypeId;
301
302    /// Build a widget that an [Inspector](crate::inspector::Inspector) can use to edit this property.
303    /// The returned value is either a simple property editor instance which contains just a
304    /// UiNode handle, or else it is a custom editor instance that contains both
305    /// the handle of the editor and the handle of the container.
306    fn create_instance(
307        &self,
308        ctx: PropertyEditorBuildContext,
309    ) -> Result<PropertyEditorInstance, InspectorError>;
310
311    /// Create a message that will tell the editor widget to update itself with the current value
312    /// of the property. This is called by [InspectorContext::sync](crate::inspector::InspectorContext::sync).
313    ///
314    /// Despite the name, this method is also permitted to send messages directly to the widget instead
315    /// of returning anything. If messages are sent directly, they should have their [UiMessage::flags] set
316    /// to [PropertyEditorMessageContext::sync_flag], as this is required to identify the message a sync message
317    /// and prevent potential infinite message loops.
318    ///
319    /// If a message is returned, the caller is responsible for setting `flags` and sending the message.
320    fn create_message(
321        &self,
322        ctx: PropertyEditorMessageContext,
323    ) -> Result<Option<UiMessage>, InspectorError>;
324
325    /// Translate messages from the editor widget created by [PropertyEditorDefinition::create_message] into
326    /// [PropertyChanged] messages that the [Inspector](crate::inspector::Inspector) widget can use to apply updates.
327    /// The given [PropertyEditorTranslationContext] contains all the relevant details of the message to be
328    /// translated.
329    fn translate_message(&self, ctx: PropertyEditorTranslationContext) -> Option<PropertyChanged>;
330}
331
332/// One entry from the list of editor definitions in a [PropertyEditorDefinitionContainer].
333pub struct PropertyEditorDefinitionContainerEntry {
334    /// A type representing the source of `property_editor`.
335    /// This value is set equal to [PropertyEditorDefinitionContainer::context_type_id] when
336    /// this entry is created by inserting `property_editor`.
337    /// The value of this type can be used to indicate whether this property editor definition
338    /// comes from a plugin.
339    pub source_type_id: TypeId,
340    /// The PropertyEditorDefinition to be used by some inspector to create
341    /// and control its child widgets.
342    pub property_editor: Box<dyn PropertyEditorDefinition>,
343}
344
345/// This is a list of [PropertyEditorDefinition] which is indexed by the type that each
346/// editor edits, as specified by [PropertyEditorDefinition::value_type_id].
347/// It also records where each entry in the list came from so that it can know whether
348/// a property editor is built-in to the Fyroxed or whether it was added by a plugin.
349/// This allows entries to be removed when a plugin is unloaded.
350pub struct PropertyEditorDefinitionContainer {
351    /// A type representing the source of PropertyEditorDefinitions that are added in the future.
352    /// For each added PropertyEditorDefinition entry, [PropertyEditorDefinitionContainerEntry::source_type_id]
353    /// is set equal to this TypeId. By default this begins as `().type_id()`, and then it can be modified
354    /// with a plugin is loaded to cause all definitions added after that point to be marked as being from
355    /// that plugin.
356    pub context_type_id: Mutex<TypeId>,
357    definitions: RwLock<FxHashMap<TypeId, PropertyEditorDefinitionContainerEntry>>,
358}
359
360impl Debug for PropertyEditorDefinitionContainer {
361    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
362        write!(f, "PropertyEditorDefinitionContainer")
363    }
364}
365
366impl Default for PropertyEditorDefinitionContainer {
367    fn default() -> Self {
368        Self {
369            context_type_id: Mutex::new(().type_id()),
370            definitions: Default::default(),
371        }
372    }
373}
374
375macro_rules! reg_array_property_editor {
376    ($container:ident, $ty:ty, $($count:literal),*) => {
377        $(
378            $container.insert(ArrayPropertyEditorDefinition::<$ty, $count>::new());
379        )*
380    }
381}
382
383macro_rules! reg_property_editor {
384    ($container:ident, $base:ident:$init:ident, $($ty:ty),*) => {
385        $(
386             $container.insert($base::<$ty>::$init());
387        )*
388    }
389}
390
391macro_rules! reg_inspectables {
392    ($container:ident, $($ty:ty),*) => {
393        $(
394             $container.insert(InspectablePropertyEditorDefinition::<$ty>::new());
395        )*
396    }
397}
398
399macro_rules! reg_matrix_property_editor {
400    ($container:ident, $base:ident[$rows:expr, $columns:expr]:$init:ident, $($ty:ty),*) => {
401        $(
402             $container.insert($base::<$rows, $columns, $ty>::$init());
403        )*
404    }
405}
406
407impl PropertyEditorDefinitionContainer {
408    pub fn empty() -> Self {
409        Self::default()
410    }
411
412    /// A container with property editors for Fyrox core types and Rust standard types.
413    pub fn with_default_editors() -> Self {
414        let container = Self::default();
415
416        // bool + InheritableVariable<bool>
417        container.insert(InheritablePropertyEditorDefinition::<bool>::new());
418        container.insert(BoolPropertyEditorDefinition);
419
420        // String
421        container.insert(StringPropertyEditorDefinition);
422        container.insert(InheritablePropertyEditorDefinition::<String>::new());
423        container.insert(VecCollectionPropertyEditorDefinition::<String>::new());
424
425        // ImmutableString
426        container.insert(ImmutableStringPropertyEditorDefinition);
427        container.insert(InheritablePropertyEditorDefinition::<ImmutableString>::new());
428        container.insert(VecCollectionPropertyEditorDefinition::<ImmutableString>::new());
429
430        // NumericType + InheritableVariable<NumericType>
431        reg_property_editor! { container, NumericPropertyEditorDefinition: default, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
432        reg_property_editor! { container, InheritablePropertyEditorDefinition: new, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
433
434        // Vector4<NumericType> + InheritableVariable<Vector4>
435        reg_property_editor! { container, Vec4PropertyEditorDefinition: default, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
436        reg_property_editor! { container, InheritablePropertyEditorDefinition: new,
437            Vector4<f64>, Vector4<f32>, Vector4<i64>, Vector4<u64>, Vector4<i32>, Vector4<u32>,
438            Vector4<i16>, Vector4<u16>, Vector4<i8>, Vector4<u8>, Vector4<usize>, Vector4<isize>
439        }
440
441        // Vector3<NumericType> + InheritableVariable<Vector3>
442        reg_property_editor! { container, Vec3PropertyEditorDefinition: default, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
443        reg_property_editor! { container, InheritablePropertyEditorDefinition: new,
444            Vector3<f64>, Vector3<f32>, Vector3<i64>, Vector3<u64>, Vector3<i32>, Vector3<u32>,
445            Vector3<i16>, Vector3<u16>, Vector3<i8>, Vector3<u8>, Vector3<usize>, Vector3<isize>
446        }
447
448        // Vector2<NumericType> + InheritableVariable<Vector2>
449        reg_property_editor! { container, Vec2PropertyEditorDefinition: default, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
450        reg_property_editor! { container, InheritablePropertyEditorDefinition: new,
451            Vector2<f64>, Vector2<f32>, Vector2<i64>, Vector2<u64>, Vector2<i32>, Vector2<u32>,
452            Vector2<i16>, Vector2<u16>, Vector2<i8>, Vector2<u8>, Vector2<usize>, Vector2<isize>
453        }
454
455        reg_matrix_property_editor! { container, MatrixPropertyEditorDefinition[2, 2]: default, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
456        reg_matrix_property_editor! { container, MatrixPropertyEditorDefinition[3, 3]: default, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
457        reg_matrix_property_editor! { container, MatrixPropertyEditorDefinition[4, 4]: default, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
458
459        // Range<NumericType> + InheritableVariable<Range<NumericType>>
460        reg_property_editor! { container, RangePropertyEditorDefinition: new, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
461        reg_property_editor! { container, InheritablePropertyEditorDefinition: new,
462            Range<f64>, Range<f32>, Range<i64>, Range<u64>, Range<i32>, Range<u32>,
463            Range<i16>, Range<u16>, Range<i8>, Range<u8>, Range<usize>, Range<isize>
464        }
465
466        // UnitQuaternion + InheritableVariable<UnitQuaternion>
467        container.insert(QuatPropertyEditorDefinition::<f64>::default());
468        container.insert(InheritablePropertyEditorDefinition::<UnitQuaternion<f64>>::new());
469        container.insert(QuatPropertyEditorDefinition::<f32>::default());
470        container.insert(InheritablePropertyEditorDefinition::<UnitQuaternion<f32>>::new());
471
472        // Rect<NumericType> + InheritableVariable<Rect<NumericType>>
473        reg_property_editor! { container, RectPropertyEditorDefinition: new, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize };
474        reg_property_editor! { container, InheritablePropertyEditorDefinition: new,
475            Rect<f64>, Rect<f32>, Rect<i64>, Rect<u64>, Rect<i32>, Rect<u32>,
476            Rect<i16>, Rect<u16>, Rect<i8>, Rect<u8>, Rect<usize>, Rect<isize>
477        }
478        reg_property_editor! { container, InheritablePropertyEditorDefinition: new,
479            Option<Rect<f64>>, Option<Rect<f32>>, Option<Rect<i64>>, Option<Rect<u64>>, Option<Rect<i32>>, Option<Rect<u32>>,
480            Option<Rect<i16>>, Option<Rect<u16>>, Option<Rect<i8>>, Option<Rect<u8>>, Option<Rect<usize>>, Option<Rect<isize>>
481        }
482        reg_property_editor! { container, EnumPropertyEditorDefinition: new_optional,
483            Rect<f64>, Rect<f32>, Rect<i64>, Rect<u64>, Rect<i32>, Rect<u32>,
484            Rect<i16>, Rect<u16>, Rect<i8>, Rect<u8>, Rect<usize>, Rect<isize>
485        }
486
487        // Option<NumericType> + InheritableVariable<Option<NumericType>>
488        reg_property_editor! { container, EnumPropertyEditorDefinition: new_optional, f64, f32, i64, u64, i32, u32, i16, u16, i8, u8, usize, isize }
489        reg_property_editor! { container, InheritablePropertyEditorDefinition: new,
490            Option<f64>, Option<f32>, Option<i64>, Option<u64>, Option<i32>, Option<u32>,
491            Option<i16>, Option<u16>, Option<i8>, Option<u8>, Option<usize>, Option<isize>
492        }
493
494        // Path
495        container.insert(PathPropertyEditorDefinition);
496        container.insert(VecCollectionPropertyEditorDefinition::<PathBuf>::new());
497
498        // Color + InheritableVariable<Color>
499        container.insert(ColorPropertyEditorDefinition);
500        container.insert(InheritablePropertyEditorDefinition::<Color>::new());
501
502        // [NumericType; 1..N]
503        reg_array_property_editor! { container, f64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
504        reg_array_property_editor! { container, f32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
505        reg_array_property_editor! { container, u64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
506        reg_array_property_editor! { container, i64, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
507        reg_array_property_editor! { container, u32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
508        reg_array_property_editor! { container, i32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
509        reg_array_property_editor! { container, u16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
510        reg_array_property_editor! { container, i16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
511        reg_array_property_editor! { container, u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
512        reg_array_property_editor! { container, i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
513        reg_array_property_editor! { container, u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
514        reg_array_property_editor! { container, usize, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
515        reg_array_property_editor! { container, isize, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
516
517        // SmoothAngle
518        container.register_inheritable_inspectable::<SmoothAngle>();
519
520        // Uuid + InheritableVariable<Uuid>
521        container.insert(UuidPropertyEditorDefinition);
522        container.insert(InheritablePropertyEditorDefinition::<Uuid>::new());
523
524        // Color Gradient.
525        container.insert(ColorGradientPropertyEditorDefinition);
526        container.insert(InheritablePropertyEditorDefinition::<ColorGradient>::new());
527
528        // Key Binding
529        container.insert(KeyBindingPropertyEditorDefinition);
530        container.insert(InheritablePropertyEditorDefinition::<KeyBinding>::new());
531
532        // Curve
533        container.insert(CurvePropertyEditorDefinition);
534        container.insert(InheritablePropertyEditorDefinition::<Curve>::new());
535
536        // UI
537        container.register_inheritable_styleable_enum::<Brush, _>();
538        container.register_inheritable_enum::<Orientation, _>();
539        container.register_inheritable_enum::<VerticalAlignment, _>();
540        container.register_inheritable_enum::<HorizontalAlignment, _>();
541        container.register_inheritable_enum::<WrapMode, _>();
542        container.register_inheritable_enum::<Primitive, _>();
543        container.register_inheritable_enum::<SizeMode, _>();
544        container.insert(EnumPropertyEditorDefinition::<CursorIcon>::new());
545        container.insert(EnumPropertyEditorDefinition::<CursorIcon>::new_optional());
546        container.insert(EnumPropertyEditorDefinition::<bool>::new_optional());
547        container.insert(InheritablePropertyEditorDefinition::<Option<bool>>::new());
548        container.insert(InheritablePropertyEditorDefinition::<Option<CursorIcon>>::new());
549
550        container.register_inheritable_vec_collection::<GradientPoint>();
551        container.register_inheritable_vec_collection::<Primitive>();
552
553        container.insert(RefCellPropertyEditorDefinition::<FormattedText>::new());
554
555        container.insert(VecCollectionPropertyEditorDefinition::<GridDimension>::new());
556        container.insert(RefCellPropertyEditorDefinition::<Vec<GridDimension>>::new());
557        container.insert(InheritablePropertyEditorDefinition::<
558            RefCell<Vec<GridDimension>>,
559        >::new());
560
561        container.insert(Utf32StringPropertyEditorDefinition);
562        container.insert(InheritablePropertyEditorDefinition::<Vec<char>>::new());
563
564        container.insert(InheritablePropertyEditorDefinition::<Thickness>::new());
565
566        container.register_inheritable_enum::<EventKind, _>();
567
568        container.register_inheritable_enum::<StretchMode, _>();
569
570        container.insert(InspectablePropertyEditorDefinition::<EventAction>::new());
571        container.register_inheritable_vec_collection::<EventAction>();
572
573        container.insert(EnumPropertyEditorDefinition::<Parameter>::new());
574
575        container.insert(EnumPropertyEditorDefinition::<TextCommitMode>::new());
576        container.insert(InheritablePropertyEditorDefinition::<TextCommitMode>::new());
577
578        container.insert(EnumPropertyEditorDefinition::<SelectionRange>::new_optional());
579        container.insert(InheritablePropertyEditorDefinition::<Option<SelectionRange>>::new());
580
581        container.register_inheritable_inspectable::<Position>();
582
583        container.insert(EnumPropertyEditorDefinition::<RcUiNodeHandle>::new_optional());
584        container.insert(InspectablePropertyEditorDefinition::<RcUiNodeHandle>::new());
585        container.insert(InspectablePropertyEditorDefinition::<RcUiNodeHandleInner>::new());
586        container.insert(InspectablePropertyEditorDefinition::<
587            Arc<Mutex<RcUiNodeHandleInner>>,
588        >::new());
589
590        container.insert(TextureSlicePropertyEditorDefinition);
591
592        // Styled.
593        container.insert(InheritablePropertyEditorDefinition::<StyledProperty<f32>>::new());
594        container.insert(StyledPropertyEditorDefinition::<f32>::new());
595
596        container.insert(InheritablePropertyEditorDefinition::<StyledProperty<Color>>::new());
597        container.insert(StyledPropertyEditorDefinition::<Color>::new());
598
599        container.insert(InheritablePropertyEditorDefinition::<
600            StyledProperty<Thickness>,
601        >::new());
602        container.insert(StyledPropertyEditorDefinition::<Thickness>::new());
603
604        container.insert(InheritablePropertyEditorDefinition::<
605            StyledProperty<TextureResource>,
606        >::new());
607        container.insert(StyledPropertyEditorDefinition::<TextureResource>::new());
608
609        reg_inspectables!(
610            container,
611            // Widgets
612            Widget,
613            Border,
614            BitField<u8>,
615            BitField<i8>,
616            BitField<u16>,
617            BitField<i16>,
618            BitField<u32>,
619            BitField<i32>,
620            BitField<u64>,
621            BitField<i64>,
622            Button,
623            Canvas,
624            Decorator,
625            DropdownList,
626            Expander,
627            Grid,
628            Image,
629            HotKeyEditor,
630            KeyBindingEditor,
631            ListViewItem,
632            ListView,
633            Menu,
634            MenuItem,
635            MessageBox,
636            NinePatch,
637            NumericUpDown<u8>,
638            NumericUpDown<i8>,
639            NumericUpDown<u16>,
640            NumericUpDown<i16>,
641            NumericUpDown<u32>,
642            NumericUpDown<i32>,
643            NumericUpDown<u64>,
644            NumericUpDown<i64>,
645            NumericUpDown<f32>,
646            NumericUpDown<f64>,
647            PathEditor,
648            Popup,
649            ProgressBar,
650            RangeEditor<u8>,
651            RangeEditor<i8>,
652            RangeEditor<u16>,
653            RangeEditor<i16>,
654            RangeEditor<u32>,
655            RangeEditor<i32>,
656            RangeEditor<u64>,
657            RangeEditor<i64>,
658            RangeEditor<f32>,
659            RangeEditor<f64>,
660            RectEditor<u8>,
661            RectEditor<i8>,
662            RectEditor<u16>,
663            RectEditor<i16>,
664            RectEditor<u32>,
665            RectEditor<i32>,
666            RectEditor<u64>,
667            RectEditor<i64>,
668            RectEditor<f32>,
669            RectEditor<f64>,
670            ScrollBar,
671            ScrollPanel,
672            StackPanel,
673            TabControl,
674            Text,
675            TextBox,
676            Tree,
677            TreeRoot,
678            UuidEditor,
679            VecEditor<u8, 2>,
680            VecEditor<i8, 2>,
681            VecEditor<u16,2>,
682            VecEditor<i16,2>,
683            VecEditor<u32,2>,
684            VecEditor<i32,2>,
685            VecEditor<u64,2>,
686            VecEditor<i64,2>,
687            VecEditor<f32,2>,
688            VecEditor<f64,2>,
689            VecEditor<u8, 3>,
690            VecEditor<i8, 3>,
691            VecEditor<u16,3>,
692            VecEditor<i16,3>,
693            VecEditor<u32,3>,
694            VecEditor<i32,3>,
695            VecEditor<u64,3>,
696            VecEditor<i64,3>,
697            VecEditor<f32,3>,
698            VecEditor<f64,3>,
699            VecEditor<u8, 4>,
700            VecEditor<i8, 4>,
701            VecEditor<u16,4>,
702            VecEditor<i16,4>,
703            VecEditor<u32,4>,
704            VecEditor<i32,4>,
705            VecEditor<u64,4>,
706            VecEditor<i64,4>,
707            VecEditor<f32,4>,
708            VecEditor<f64,4>,
709            VectorImage,
710            Window,
711            WrapPanel,
712            // Structs
713            GradientPoint,
714            Thickness,
715            FormattedText,
716            GridDimension
717        );
718
719        container
720    }
721
722    /// Add an already boxed dynamic PropertyEditorDefinition to the list.
723    /// If this container already had a PropertyEditorDefinition for the same type,
724    /// the old property editor is removed and returned.
725    pub fn insert_raw(
726        &self,
727        definition: Box<dyn PropertyEditorDefinition>,
728    ) -> Option<PropertyEditorDefinitionContainerEntry> {
729        self.definitions.write().insert(
730            definition.value_type_id(),
731            PropertyEditorDefinitionContainerEntry {
732                source_type_id: *self.context_type_id.lock(),
733                property_editor: definition,
734            },
735        )
736    }
737
738    /// Consume a given collection of property editors and add each entry into this collection.
739    /// *Every* entry from the given collection is marked as having the current source type;
740    /// whatever sources they may have had in their original container is forgotten.
741    pub fn merge(&self, other: Self) {
742        for (_, definition) in other.definitions.into_inner() {
743            self.insert_raw(definition.property_editor);
744        }
745    }
746
747    /// Move a PropertyEditorDefinition into the list, where it will automatically be boxed.
748    /// If this container already had a PropertyEditorDefinition for the same type,
749    /// the old property editor is removed and returned.
750    pub fn insert<T>(&self, definition: T) -> Option<PropertyEditorDefinitionContainerEntry>
751    where
752        T: PropertyEditorDefinition + 'static,
753    {
754        self.definitions.write().insert(
755            definition.value_type_id(),
756            PropertyEditorDefinitionContainerEntry {
757                source_type_id: *self.context_type_id.lock(),
758                property_editor: Box::new(definition),
759            },
760        )
761    }
762
763    /// Inserts the default property editor for `Vec<T>` and `InheritableVariable<Vec<T>>`.
764    /// Panic if these types already have editor definitions.
765    pub fn register_inheritable_vec_collection<T>(&self)
766    where
767        T: CollectionItem + FieldValue,
768    {
769        assert!(self
770            .insert(VecCollectionPropertyEditorDefinition::<T>::new())
771            .is_none());
772        assert!(self
773            .insert(InheritablePropertyEditorDefinition::<Vec<T>>::new())
774            .is_none());
775    }
776
777    /// Insert a [InspectablePropertyEditorDefinition] for the given type.
778    /// This is a creates a generic property editor that is just a nested
779    /// inspector for the properties of the value, with an [Expander]
780    /// to allow the inner inspector to be hidden.
781    ///
782    /// A property editor definition for `InheritableVariable<T>` is also inserted.
783    ///
784    /// Panic if these types already have editor definitions.
785    pub fn register_inheritable_inspectable<T>(&self)
786    where
787        T: Reflect + FieldValue,
788    {
789        assert!(self
790            .insert(InspectablePropertyEditorDefinition::<T>::new())
791            .is_none());
792        assert!(self
793            .insert(InheritablePropertyEditorDefinition::<T>::new())
794            .is_none());
795    }
796
797    pub fn register_inheritable_styleable_inspectable<T>(&self)
798    where
799        T: Reflect + FieldValue,
800    {
801        assert!(self
802            .insert(InspectablePropertyEditorDefinition::<T>::new())
803            .is_none());
804        assert!(self
805            .insert(InheritablePropertyEditorDefinition::<T>::new())
806            .is_none());
807        assert!(self
808            .insert(InheritablePropertyEditorDefinition::<StyledProperty<T>>::new())
809            .is_none());
810        assert!(self
811            .insert(StyledPropertyEditorDefinition::<T>::new())
812            .is_none());
813    }
814
815    /// Insert property editor definitions to allow enum T to be edited
816    /// using a dropdown list, as well as `InheritableVariable<T>`.
817    ///
818    /// Panic if these types already have editor definitions.
819    pub fn register_inheritable_enum<T, E: Debug>(&self)
820    where
821        T: InspectableEnum + FieldValue + VariantNames + AsRef<str> + FromStr<Err = E> + Debug,
822    {
823        assert!(self
824            .insert(EnumPropertyEditorDefinition::<T>::new())
825            .is_none());
826        assert!(self
827            .insert(InheritablePropertyEditorDefinition::<T>::new())
828            .is_none());
829    }
830
831    pub fn register_inheritable_styleable_enum<T, E: Debug>(&self)
832    where
833        T: InspectableEnum + FieldValue + VariantNames + AsRef<str> + FromStr<Err = E> + Debug,
834    {
835        assert!(self
836            .insert(EnumPropertyEditorDefinition::<T>::new())
837            .is_none());
838        assert!(self
839            .insert(InheritablePropertyEditorDefinition::<T>::new())
840            .is_none());
841        assert!(self
842            .insert(InheritablePropertyEditorDefinition::<StyledProperty<T>>::new())
843            .is_none());
844        assert!(self
845            .insert(StyledPropertyEditorDefinition::<T>::new())
846            .is_none());
847    }
848
849    /// Insert property editor definitions to allow `Option<T>` to be edited
850    /// as well as `InheritableVariable<T>`.
851    ///
852    /// Panic if these types already have editor definitions.
853    pub fn register_inheritable_option<T>(&self)
854    where
855        T: InspectableEnum + FieldValue + Default,
856    {
857        assert!(self
858            .insert(EnumPropertyEditorDefinition::<T>::new_optional())
859            .is_none());
860        assert!(self
861            .insert(InheritablePropertyEditorDefinition::<Option<T>>::new())
862            .is_none());
863    }
864
865    /// Direct read-only access to all the editor definitions.
866    pub fn definitions(
867        &self,
868    ) -> RwLockReadGuard<FxHashMap<TypeId, PropertyEditorDefinitionContainerEntry>> {
869        self.definitions.read()
870    }
871
872    /// Direct and unrestricted access to all the editor definitions.
873    pub fn definitions_mut(
874        &self,
875    ) -> RwLockWriteGuard<FxHashMap<TypeId, PropertyEditorDefinitionContainerEntry>> {
876        self.definitions.write()
877    }
878}