Skip to main content

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