Add support for editing dictionary keys that are structures

This commit is contained in:
Wojtek Figat
2023-05-24 22:58:07 +02:00
parent 7efb3e3f3d
commit e10aa1ff58
2 changed files with 45 additions and 13 deletions

View File

@@ -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);

View File

@@ -110,6 +110,25 @@ namespace FlaxEditor.GUI.ContextMenu
_isSubMenu = true;
}
/// <summary>
/// Shows the empty menu popup o na screen.
/// </summary>
/// <param name="control">The target control.</param>
/// <param name="area">The target control area to cover.</param>
/// <returns>Created popup.</returns>
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;
}
/// <summary>
/// Show context menu over given control.
/// </summary>