Files
2026-09-21 12:15:57 +03:00

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