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