From af08dc1c692f91cb155e7f1ea91cc3faa8067bdb Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 13 May 2024 16:08:50 +0200 Subject: [PATCH] Fix `ReadOnly` attribute handling in collection editors --- .../CustomEditors/Editors/CollectionEditor.cs | 35 +++++++--- .../CustomEditors/Editors/DictionaryEditor.cs | 18 ++--- .../CustomEditors/Editors/GenericEditor.cs | 67 +++++++++++-------- 3 files changed, 71 insertions(+), 49 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs index d7d16083e..de7a5d1bf 100644 --- a/Source/Editor/CustomEditors/Editors/CollectionEditor.cs +++ b/Source/Editor/CustomEditors/Editors/CollectionEditor.cs @@ -57,17 +57,18 @@ namespace FlaxEditor.CustomEditors.Editors menu.ItemsContainer.RemoveChildren(); menu.AddButton("Copy", linkedEditor.Copy); - var paste = menu.AddButton("Paste", linkedEditor.Paste); - paste.Enabled = linkedEditor.CanPaste; + var b = menu.AddButton("Paste", linkedEditor.Paste); + b.Enabled = linkedEditor.CanPaste && !Editor._readOnly; menu.AddSeparator(); - var moveUpButton = menu.AddButton("Move up", OnMoveUpClicked); - moveUpButton.Enabled = Index > 0; + b = menu.AddButton("Move up", OnMoveUpClicked); + b.Enabled = Index > 0 && !Editor._readOnly; - var moveDownButton = menu.AddButton("Move down", OnMoveDownClicked); - moveDownButton.Enabled = Index + 1 < Editor.Count; - - menu.AddButton("Remove", OnRemoveClicked); + b = menu.AddButton("Move down", OnMoveDownClicked); + b.Enabled = Index + 1 < Editor.Count && !Editor._readOnly; + + b = menu.AddButton("Remove", OnRemoveClicked); + b.Enabled = !Editor._readOnly; } private void OnMoveUpClicked() @@ -177,6 +178,7 @@ namespace FlaxEditor.CustomEditors.Editors private IntValueBox _sizeBox; private Color _background; private int _elementsCount, _minCount, _maxCount; + private bool _readOnly; private bool _canResize; private bool _canReorderItems; private CollectionAttribute.DisplayType _displayType; @@ -209,6 +211,7 @@ namespace FlaxEditor.CustomEditors.Editors return; var size = Count; + _readOnly = false; _canResize = true; _canReorderItems = true; _minCount = 0; @@ -225,6 +228,7 @@ namespace FlaxEditor.CustomEditors.Editors if (collection != null) { _canResize = !collection.ReadOnly; + _readOnly = collection.ReadOnly; _minCount = collection.MinCount; _maxCount = collection.MaxCount; _canReorderItems = collection.CanReorderItems; @@ -235,6 +239,12 @@ namespace FlaxEditor.CustomEditors.Editors spacing = collection.Spacing; _displayType = collection.Display; } + if (attributes != null && attributes.Any(x => x is ReadOnlyAttribute)) + { + _readOnly = true; + _canResize = false; + _canReorderItems = false; + } if (_maxCount == 0) _maxCount = ushort.MaxValue; _canResize &= _minCount < _maxCount; @@ -243,8 +253,7 @@ namespace FlaxEditor.CustomEditors.Editors dragArea.CustomControl.Editor = this; dragArea.CustomControl.ElementType = ElementType; - // Check for the AssetReferenceAttribute. In JSON assets, it can be used to filter - // which scripts can be dragged over and dropped on this collection editor. + // Check for the AssetReferenceAttribute. In JSON assets, it can be used to filter which scripts can be dragged over and dropped on this collection editor var assetReference = (AssetReferenceAttribute)attributes?.FirstOrDefault(x => x is AssetReferenceAttribute); if (assetReference != null) { @@ -333,6 +342,8 @@ namespace FlaxEditor.CustomEditors.Editors var property = panel.AddPropertyItem(itemLabel); var itemLayout = (LayoutElementsContainer)property; itemLabel.LinkedEditor = itemLayout.Object(new ListValueContainer(elementType, i, Values, attributes), overrideEditor); + if (_readOnly && itemLayout.Children.Count > 0) + GenericEditor.OnReadOnlyProperty(itemLayout); } else if (_displayType == CollectionAttribute.DisplayType.Header || (_displayType == CollectionAttribute.DisplayType.Default && !single)) { @@ -340,13 +351,15 @@ namespace FlaxEditor.CustomEditors.Editors cdp.CustomControl.Setup(this, i, _canReorderItems); var itemLayout = cdp.VerticalPanel(); cdp.CustomControl.LinkedEditor = itemLayout.Object(new ListValueContainer(elementType, i, Values, attributes), overrideEditor); + if (_readOnly && itemLayout.Children.Count > 0) + GenericEditor.OnReadOnlyProperty(itemLayout); } } } _elementsCount = size; // Add/Remove buttons - if (_canResize) + if (_canResize && !_readOnly) { var panel = dragArea.HorizontalPanel(); panel.Panel.Size = new Float2(0, 20); diff --git a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs index da60aaefd..42f90db6a 100644 --- a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs +++ b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs @@ -131,7 +131,7 @@ namespace FlaxEditor.CustomEditors.Editors /// public override bool OnMouseDoubleClick(Float2 location, MouseButton button) { - if (button == MouseButton.Left) + if (button == MouseButton.Left && _editor._canEditKeys) { OnEditClicked(null); return true; @@ -156,6 +156,7 @@ namespace FlaxEditor.CustomEditors.Editors private bool _readOnly; private bool _notNullItems; private bool _canEditKeys; + private bool _canEditValues; private bool _keyEdited; private CollectionAttribute.DisplayType _displayType; @@ -197,6 +198,11 @@ namespace FlaxEditor.CustomEditors.Editors spacing = collection.Spacing; _displayType = collection.Display; } + if (attributes != null && attributes.Any(x => x is ReadOnlyAttribute)) + { + _readOnly = true; + _canEditKeys = false; + } // Size if (layout.ContainerControl is DropPanel dropPanel) @@ -239,14 +245,6 @@ namespace FlaxEditor.CustomEditors.Editors var keysEnumerable = ((IDictionary)Values[0]).Keys.OfType(); var keys = keysEnumerable as object[] ?? keysEnumerable.ToArray(); var valuesType = new ScriptType(valueType); - - bool single = valuesType.IsPrimitive || - valuesType.Equals(new ScriptType(typeof(string))) || - valuesType.IsEnum || - (valuesType.GetFields().Length == 1 && valuesType.GetProperties().Length == 0) || - (valuesType.GetProperties().Length == 1 && valuesType.GetFields().Length == 0) || - valuesType.Equals(new ScriptType(typeof(JsonAsset))) || - valuesType.Equals(new ScriptType(typeof(SettingsBase))); // Use separate layout cells for each collection items to improve layout updates for them in separation var useSharedLayout = valueType.IsPrimitive || valueType.IsEnum; @@ -263,6 +261,8 @@ namespace FlaxEditor.CustomEditors.Editors var property = panel.AddPropertyItem(new DictionaryItemLabel(this, key)); var itemLayout = useSharedLayout ? (LayoutElementsContainer)property : property.VerticalPanel(); itemLayout.Object(new DictionaryValueContainer(valuesType, key, Values), overrideEditor); + if (_readOnly && itemLayout.Children.Count > 0) + GenericEditor.OnReadOnlyProperty(itemLayout); } } _elementsCount = size; diff --git a/Source/Editor/CustomEditors/Editors/GenericEditor.cs b/Source/Editor/CustomEditors/Editors/GenericEditor.cs index 63e103daa..ec75926d9 100644 --- a/Source/Editor/CustomEditors/Editors/GenericEditor.cs +++ b/Source/Editor/CustomEditors/Editors/GenericEditor.cs @@ -581,6 +581,43 @@ namespace FlaxEditor.CustomEditors.Editors return layout; } + internal static void OnReadOnlyProperty(LayoutElementsContainer itemLayout, int labelIndex = -1) + { + PropertiesListElement list = null; + int firstChildControlIndex = 0; + bool disableSingle = true; + var control = itemLayout.Children[itemLayout.Children.Count - 1]; + if (control is GroupElement group && group.Children.Count > 0) + { + list = group.Children[0] as PropertiesListElement; + disableSingle = false; // Disable all nested editors + } + else if (control is PropertiesListElement list1 && labelIndex != -1) + { + list = list1; + firstChildControlIndex = list.Labels[labelIndex].FirstChildControlIndex; + } + else if (control?.Control != null) + { + control.Control.Enabled = false; + } + + if (list != null) + { + // Disable controls added to the editor + var count = list.Properties.Children.Count; + for (int j = firstChildControlIndex; j < count; j++) + { + var child = list.Properties.Children[j]; + if (disableSingle && child is PropertyNameLabel) + break; + + if (child != null) + child.Enabled = false; + } + } + } + /// /// Evaluate the cache for a given property item. /// @@ -660,35 +697,7 @@ namespace FlaxEditor.CustomEditors.Editors if (item.IsReadOnly && itemLayout.Children.Count > 0) { - PropertiesListElement list = null; - int firstChildControlIndex = 0; - bool disableSingle = true; - var control = itemLayout.Children[itemLayout.Children.Count - 1]; - if (control is GroupElement group && group.Children.Count > 0) - { - list = group.Children[0] as PropertiesListElement; - disableSingle = false; // Disable all nested editors - } - else if (control is PropertiesListElement list1) - { - list = list1; - firstChildControlIndex = list.Labels[labelIndex].FirstChildControlIndex; - } - - if (list != null) - { - // Disable controls added to the editor - var count = list.Properties.Children.Count; - for (int j = firstChildControlIndex; j < count; j++) - { - var child = list.Properties.Children[j]; - if (disableSingle && child is PropertyNameLabel) - break; - - if (child != null) - child.Enabled = false; - } - } + OnReadOnlyProperty(itemLayout, labelIndex); } EvaluateVisibleIf(itemLayout, item, labelIndex);