168 lines
5.8 KiB
C#
168 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace Alchemy.Editor.Elements
|
|
{
|
|
public sealed class DictionaryField : HashMapFieldBase
|
|
{
|
|
public DictionaryField(object collection, string label) : base(collection, label)
|
|
{
|
|
if (collection != null)
|
|
{
|
|
keyType = collection.GetType().GenericTypeArguments[0];
|
|
valueType = collection.GetType().GenericTypeArguments[1];
|
|
kvType = typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType);
|
|
}
|
|
}
|
|
|
|
public override string CollectionTypeName => TypeName;
|
|
|
|
const string TypeName = "Dictionary";
|
|
const string KeyName = "Key";
|
|
const string ValueName = "Value";
|
|
|
|
readonly Type keyType;
|
|
readonly Type valueType;
|
|
readonly Type kvType;
|
|
|
|
public override bool CheckElement(object element)
|
|
{
|
|
var keyObj = ReflectionHelper.GetPropertyValue(element, element.GetType(), KeyName);
|
|
if (keyObj is string str && string.IsNullOrEmpty(str)) return true;
|
|
if (keyObj == null) return true;
|
|
return (bool)ReflectionHelper.Invoke(Collection, "ContainsKey", keyObj);
|
|
}
|
|
|
|
public override object CreateElement()
|
|
{
|
|
var keyObj = TypeHelper.CreateDefaultInstance(keyType);
|
|
var valueObj = TypeHelper.CreateDefaultInstance(valueType);
|
|
return Activator.CreateInstance(kvType, keyObj, valueObj);
|
|
}
|
|
|
|
public override void AddElement(object element)
|
|
{
|
|
var keyObj = ReflectionHelper.GetPropertyValue(element, kvType, KeyName);
|
|
var valueObj = ReflectionHelper.GetPropertyValue(element, kvType, ValueName);
|
|
ReflectionHelper.Invoke(Collection, "Add", keyObj, valueObj);
|
|
}
|
|
|
|
public override bool RemoveElement(object element)
|
|
{
|
|
return (bool)ReflectionHelper.Invoke(Collection, "Remove", ReflectionHelper.GetPropertyValue(element, kvType, KeyName));
|
|
}
|
|
|
|
public override void ClearElements()
|
|
{
|
|
ReflectionHelper.Invoke(Collection, "Clear");
|
|
}
|
|
|
|
public override HashMapItemBase CreateItem(object collection, object elementObj, string label)
|
|
{
|
|
return new Item(collection, elementObj);
|
|
}
|
|
|
|
public sealed class Item : HashMapItemBase
|
|
{
|
|
public Item(object collection, object keyValuePair)
|
|
{
|
|
var box = new Box()
|
|
{
|
|
style = {
|
|
marginBottom = 3.5f,
|
|
marginRight = -2f,
|
|
flexDirection = FlexDirection.Row
|
|
}
|
|
};
|
|
|
|
kvType = keyValuePair.GetType();
|
|
var keyType = kvType.GenericTypeArguments[0];
|
|
var valueType = kvType.GenericTypeArguments[1];
|
|
|
|
key = ReflectionHelper.GetPropertyValue(keyValuePair, kvType, KeyName);
|
|
value = ReflectionHelper.GetPropertyValue(keyValuePair, kvType, ValueName);
|
|
|
|
this.collection = collection;
|
|
this.keyValuePair = keyValuePair;
|
|
|
|
var keyValueElement = new VisualElement()
|
|
{
|
|
style = {
|
|
flexDirection = FlexDirection.Column,
|
|
flexGrow = 1f
|
|
}
|
|
};
|
|
box.Add(keyValueElement);
|
|
|
|
keyField = new GenericField(key, keyType, KeyName)
|
|
{
|
|
style = { flexGrow = 1f }
|
|
};
|
|
keyField.OnValueChanged += SetKey;
|
|
keyValueElement.Add(keyField);
|
|
|
|
valueField = new GenericField(value, valueType, ValueName)
|
|
{
|
|
style = { flexGrow = 1f }
|
|
};
|
|
valueField.OnValueChanged += SetValue;
|
|
keyValueElement.Add(valueField);
|
|
|
|
var closeButton = new Button(() => OnClose?.Invoke())
|
|
{
|
|
style = {
|
|
width = EditorGUIUtility.singleLineHeight,
|
|
height = EditorGUIUtility.singleLineHeight,
|
|
unityFontStyleAndWeight = FontStyle.Bold,
|
|
fontSize = 10f
|
|
},
|
|
text = "X",
|
|
};
|
|
box.Add(closeButton);
|
|
Add(box);
|
|
}
|
|
|
|
readonly GenericField keyField;
|
|
readonly GenericField valueField;
|
|
|
|
readonly object collection;
|
|
public override object Value => keyValuePair;
|
|
|
|
object key;
|
|
object value;
|
|
object keyValuePair;
|
|
readonly Type kvType;
|
|
|
|
public override void Lock()
|
|
{
|
|
keyField.SetEnabled(false);
|
|
valueField.OnValueChanged -= SetValue;
|
|
valueField.OnValueChanged += x =>
|
|
{
|
|
value = x;
|
|
keyValuePair = Activator.CreateInstance(kvType, key, value);
|
|
ReflectionHelper.GetProperty(collection.GetType(), "Item").SetValue(collection, value, new object[] { key });
|
|
OnValueChanged?.Invoke(keyValuePair);
|
|
};
|
|
}
|
|
|
|
void SetKey(object obj)
|
|
{
|
|
key = obj;
|
|
keyValuePair = Activator.CreateInstance(kvType, key, value);
|
|
OnValueChanged?.Invoke(keyValuePair);
|
|
}
|
|
|
|
void SetValue(object obj)
|
|
{
|
|
value = obj;
|
|
keyValuePair = Activator.CreateInstance(kvType, key, value);
|
|
OnValueChanged?.Invoke(keyValuePair);
|
|
}
|
|
}
|
|
}
|
|
}
|