From e10aa1ff58a4c520ac6b0a0a5d47053dc0cfdd11 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 24 May 2023 22:58:07 +0200 Subject: [PATCH] Add support for editing dictionary keys that are structures --- .../CustomEditors/Editors/DictionaryEditor.cs | 39 ++++++++++++------- .../Editor/GUI/ContextMenu/ContextMenuBase.cs | 19 +++++++++ 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs index 1b9a7cca1..18500fc08 100644 --- a/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs +++ b/Source/Editor/CustomEditors/Editors/DictionaryEditor.cs @@ -2,7 +2,6 @@ using System; using System.Collections; -using System.Collections.Generic; using System.Linq; using FlaxEditor.CustomEditors.Elements; using FlaxEditor.CustomEditors.GUI; @@ -45,8 +44,8 @@ namespace FlaxEditor.CustomEditors.Editors private void OnSetupContextMenu(PropertyNameLabel label, ContextMenu menu, CustomEditor linkedEditor) { - menu.AddSeparator(); - + if (menu.Items.Any()) + menu.AddSeparator(); menu.AddButton("Remove", OnRemoveClicked).Enabled = !_editor._readOnly; menu.AddButton("Edit", OnEditClicked).Enabled = _editor._canEditKeys; } @@ -61,6 +60,7 @@ namespace FlaxEditor.CustomEditors.Editors var keyType = _editor.Values.Type.GetGenericArguments()[0]; if (keyType == typeof(string) || keyType.IsPrimitive) { + // Edit as text var popup = RenamePopup.Show(Parent, Rectangle.Margin(Bounds, Margin), Text, false); popup.Validate += (renamePopup, value) => { @@ -78,7 +78,6 @@ namespace FlaxEditor.CustomEditors.Editors newKey = JsonSerializer.Deserialize(renamePopup.Text, keyType); else newKey = renamePopup.Text; - _editor.ChangeKey(_key, newKey); _key = newKey; Text = _key.ToString(); @@ -86,6 +85,7 @@ namespace FlaxEditor.CustomEditors.Editors } else if (keyType.IsEnum) { + // Edit via enum picker var popup = RenamePopup.Show(Parent, Rectangle.Margin(Bounds, Margin), Text, false); var picker = new EnumComboBox(keyType) { @@ -108,7 +108,21 @@ namespace FlaxEditor.CustomEditors.Editors } else { - throw new NotImplementedException("Missing editing for dictionary key type " + keyType); + // Generic editor + var popup = ContextMenuBase.ShowEmptyMenu(Parent, Rectangle.Margin(Bounds, Margin)); + var presenter = new CustomEditorPresenter(null); + presenter.Panel.AnchorPreset = AnchorPresets.StretchAll; + presenter.Panel.IsScrollable = false; + presenter.Panel.Parent = popup; + presenter.Select(_key); + presenter.Modified += () => + { + popup.Hide(); + object newKey = presenter.Selection[0]; + _editor.ChangeKey(_key, newKey); + _key = newKey; + Text = _key?.ToString(); + }; } } @@ -159,7 +173,7 @@ namespace FlaxEditor.CustomEditors.Editors var argTypes = type.GetGenericArguments(); var keyType = argTypes[0]; var valueType = argTypes[1]; - _canEditKeys = keyType == typeof(string) || keyType.IsPrimitive || keyType.IsEnum; + _canEditKeys = keyType == typeof(string) || keyType.IsPrimitive || keyType.IsEnum || keyType.IsValueType; _background = FlaxEngine.GUI.Style.Current.CollectionBackgroundColor; _readOnly = false; _notNullItems = false; @@ -382,6 +396,7 @@ namespace FlaxEditor.CustomEditors.Editors int newItemsLeft = newSize - oldSize; while (newItemsLeft-- > 0) { + object newKey = null; if (keyType.IsPrimitive) { long uniqueKey = 0; @@ -400,8 +415,7 @@ namespace FlaxEditor.CustomEditors.Editors } } } while (!isUnique); - - newValues[Convert.ChangeType(uniqueKey, keyType)] = TypeUtils.GetDefaultValue(new ScriptType(valueType)); + newKey = Convert.ChangeType(uniqueKey, keyType); } else if (keyType.IsEnum) { @@ -421,8 +435,7 @@ namespace FlaxEditor.CustomEditors.Editors } } } while (!isUnique && uniqueKeyIndex < enumValues.Length); - - newValues[enumValues.GetValue(uniqueKeyIndex)] = TypeUtils.GetDefaultValue(new ScriptType(valueType)); + newKey = enumValues.GetValue(uniqueKeyIndex); } else if (keyType == typeof(string)) { @@ -441,13 +454,13 @@ namespace FlaxEditor.CustomEditors.Editors } } } while (!isUnique); - - newValues[uniqueKey] = TypeUtils.GetDefaultValue(new ScriptType(valueType)); + newKey = uniqueKey; } else { - throw new InvalidOperationException(); + newKey = TypeUtils.GetDefaultValue(new ScriptType(keyType)); } + newValues[newKey] = TypeUtils.GetDefaultValue(new ScriptType(valueType)); } SetValue(newValues); diff --git a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs index 27d47345d..7ecd197eb 100644 --- a/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs +++ b/Source/Editor/GUI/ContextMenu/ContextMenuBase.cs @@ -110,6 +110,25 @@ namespace FlaxEditor.GUI.ContextMenu _isSubMenu = true; } + /// + /// Shows the empty menu popup o na screen. + /// + /// The target control. + /// The target control area to cover. + /// Created popup. + public static ContextMenuBase ShowEmptyMenu(Control control, Rectangle area) + { + // Calculate the control size in the window space to handle scaled controls + var upperLeft = control.PointToWindow(area.UpperLeft); + var bottomRight = control.PointToWindow(area.BottomRight); + var size = bottomRight - upperLeft; + + var popup = new ContextMenuBase(); + popup.Size = size; + popup.Show(control, area.Location + new Float2(0, (size.Y - popup.Height) * 0.5f)); + return popup; + } + /// /// Show context menu over given control. ///