338 lines
9.9 KiB
C#
338 lines
9.9 KiB
C#
#nullable enable
|
|
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace UVC.UIToolkit
|
|
{
|
|
/// <summary>
|
|
/// Enum 속성 View 클래스입니다.
|
|
/// UTKEnumDropDown을 사용하여 열거형 값을 표시/편집합니다.
|
|
/// ReadOnly 상태에서는 UTKInputField로 표시됩니다.
|
|
/// </summary>
|
|
[UxmlElement]
|
|
public partial class UTKEnumPropertyItemView : UTKPropertyItemViewBase, IUTKPropertyItemView<Enum>
|
|
{
|
|
#region Fields
|
|
private UTKEnumDropDown? _enumDropdown;
|
|
private UTKInputField? _readOnlyField;
|
|
|
|
private Enum? _value;
|
|
private Type? _enumType;
|
|
|
|
private IUTKPropertyItem<Enum>? _boundData;
|
|
#endregion
|
|
|
|
#region Properties
|
|
protected override string ViewTypeName => "UTKEnumPropertyItemView";
|
|
|
|
/// <summary>현재 값</summary>
|
|
public Enum Value
|
|
{
|
|
get => _value!;
|
|
set
|
|
{
|
|
if (_value != value)
|
|
{
|
|
_value = value;
|
|
_enumType = value?.GetType();
|
|
UpdateValueUI();
|
|
OnValueChanged?.Invoke(value!);
|
|
|
|
if (_boundData != null && _boundData.Value != value)
|
|
{
|
|
_boundData.Value = value!;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>열거형 타입</summary>
|
|
public Type? EnumType => _enumType;
|
|
#endregion
|
|
|
|
#region Events
|
|
public event Action<Enum>? OnValueChanged;
|
|
#endregion
|
|
|
|
#region Constructor
|
|
public UTKEnumPropertyItemView() : base()
|
|
{
|
|
InitializeUI();
|
|
}
|
|
|
|
public UTKEnumPropertyItemView(UTKEnumPropertyItem data) : base()
|
|
{
|
|
if (data == null) throw new ArgumentNullException(nameof(data));
|
|
|
|
_value = data.Value;
|
|
_enumType = data.Value?.GetType();
|
|
Label = data.Name;
|
|
_isReadOnly = data.IsReadOnly;
|
|
InitializeUI();
|
|
Bind(data);
|
|
}
|
|
|
|
public UTKEnumPropertyItemView(string label, Enum initialValue) : base()
|
|
{
|
|
_value = initialValue ?? throw new ArgumentNullException(nameof(initialValue));
|
|
_enumType = initialValue.GetType();
|
|
Label = label;
|
|
InitializeUI();
|
|
}
|
|
#endregion
|
|
|
|
#region Initialization
|
|
private void InitializeUI()
|
|
{
|
|
AddToClassList("utk-property-item-view");
|
|
AddToClassList("utk-property-item-view--enum");
|
|
|
|
if (!CreateUIFromUxml())
|
|
{
|
|
CreateUIFallback();
|
|
}
|
|
|
|
// UXML에서 요소 가져오기
|
|
QueryUIElements();
|
|
|
|
// 이벤트 등록
|
|
RegisterEvents();
|
|
|
|
UpdateValueUI();
|
|
UpdateReadOnlyState();
|
|
}
|
|
|
|
private void QueryUIElements()
|
|
{
|
|
if (_valueContainer == null) return;
|
|
|
|
if (IsReadOnly)
|
|
{
|
|
// ReadOnly: UTKInputField 사용
|
|
_readOnlyField = this.Q<UTKInputField>("readonly-field");
|
|
if (_readOnlyField == null)
|
|
{
|
|
_readOnlyField = new UTKInputField { name = "readonly-field" };
|
|
_readOnlyField.AddToClassList("utk-property-item-view__readonly-field");
|
|
_valueContainer.Add(_readOnlyField);
|
|
}
|
|
_readOnlyField.Value = _value?.ToString() ?? "";
|
|
_readOnlyField.isReadOnly = true;
|
|
|
|
// Dropdown 숨기기
|
|
if (_enumDropdown != null)
|
|
{
|
|
_enumDropdown.style.display = DisplayStyle.None;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Editable: UTKEnumDropDown 사용
|
|
_enumDropdown = this.Q<UTKEnumDropDown>("enum-dropdown");
|
|
if (_enumDropdown == null)
|
|
{
|
|
_enumDropdown = new UTKEnumDropDown { name = "enum-dropdown" };
|
|
_enumDropdown.AddToClassList("utk-property-item-view__dropdown");
|
|
_valueContainer.Add(_enumDropdown);
|
|
}
|
|
if (_value != null)
|
|
{
|
|
_enumDropdown.Init(_value);
|
|
}
|
|
_enumDropdown.IsEnabled = true;
|
|
_enumDropdown.style.display = DisplayStyle.Flex;
|
|
|
|
// ReadOnly 필드 숨기기
|
|
if (_readOnlyField != null)
|
|
{
|
|
_readOnlyField.style.display = DisplayStyle.None;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RegisterEvents()
|
|
{
|
|
if (_enumDropdown != null)
|
|
{
|
|
_enumDropdown.OnValueChanged += OnEnumDropdownChanged;
|
|
}
|
|
}
|
|
|
|
private void UnregisterEvents()
|
|
{
|
|
if (_enumDropdown != null)
|
|
{
|
|
_enumDropdown.OnValueChanged -= OnEnumDropdownChanged;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Override Methods
|
|
protected override void CreateValueUI(VisualElement container)
|
|
{
|
|
// UXML/QueryUIElements 기반으로 생성하므로 여기서는 생성하지 않음
|
|
}
|
|
|
|
public override void RefreshUI()
|
|
{
|
|
UpdateValueUI();
|
|
}
|
|
|
|
protected override void OnReadOnlyStateChanged(bool isReadOnly)
|
|
{
|
|
if (_valueContainer == null) return;
|
|
|
|
if (isReadOnly)
|
|
{
|
|
// Dropdown → InputField 전환
|
|
if (_readOnlyField == null)
|
|
{
|
|
_readOnlyField = new UTKInputField { name = "readonly-field" };
|
|
_readOnlyField.AddToClassList("utk-property-item-view__readonly-field");
|
|
_valueContainer.Add(_readOnlyField);
|
|
}
|
|
_readOnlyField.Value = _value?.ToString() ?? "";
|
|
_readOnlyField.isReadOnly = true;
|
|
_readOnlyField.style.display = DisplayStyle.Flex;
|
|
|
|
if (_enumDropdown != null)
|
|
{
|
|
_enumDropdown.style.display = DisplayStyle.None;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// InputField → Dropdown 전환
|
|
if (_enumDropdown == null)
|
|
{
|
|
_enumDropdown = new UTKEnumDropDown { name = "enum-dropdown" };
|
|
_enumDropdown.AddToClassList("utk-property-item-view__dropdown");
|
|
_valueContainer.Add(_enumDropdown);
|
|
if (_value != null)
|
|
{
|
|
_enumDropdown.Init(_value);
|
|
}
|
|
RegisterEvents();
|
|
}
|
|
_enumDropdown.IsEnabled = true;
|
|
_enumDropdown.style.display = DisplayStyle.Flex;
|
|
|
|
if (_readOnlyField != null)
|
|
{
|
|
_readOnlyField.style.display = DisplayStyle.None;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Event Handling
|
|
private void OnEnumDropdownChanged(Enum? newValue)
|
|
{
|
|
if (newValue != null && !Equals(_value, newValue))
|
|
{
|
|
_value = newValue;
|
|
OnValueChanged?.Invoke(newValue);
|
|
|
|
if (_boundData != null && !Equals(_boundData.Value, newValue))
|
|
{
|
|
_boundData.Value = newValue;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Value Update
|
|
private void UpdateValueUI()
|
|
{
|
|
if (IsReadOnly && _readOnlyField != null)
|
|
{
|
|
_readOnlyField.Value = _value?.ToString() ?? "";
|
|
}
|
|
else if (_enumDropdown != null && _value != null)
|
|
{
|
|
if (_enumDropdown.Value != _value)
|
|
{
|
|
_enumDropdown.Value = _value;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Data Binding
|
|
public void Bind(IUTKPropertyItem data)
|
|
{
|
|
if (data is IUTKPropertyItem<Enum> enumData)
|
|
{
|
|
Bind(enumData);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"[UTKEnumPropertyItemView] Cannot bind to non-Enum data: {data.GetType().Name}");
|
|
}
|
|
}
|
|
|
|
public void Bind(IUTKPropertyItem<Enum> data)
|
|
{
|
|
Unbind();
|
|
|
|
_boundData = data;
|
|
|
|
Label = data.Name;
|
|
_value = data.Value;
|
|
_enumType = data.Value?.GetType();
|
|
IsReadOnly = data.IsReadOnly;
|
|
IsVisible = data.IsVisible;
|
|
TooltipText = data.Tooltip;
|
|
|
|
if (_enumDropdown != null && _value != null)
|
|
{
|
|
_enumDropdown.Init(_value);
|
|
}
|
|
|
|
data.OnTypedValueChanged += OnDataValueChanged;
|
|
|
|
UpdateValueUI();
|
|
UpdateReadOnlyState();
|
|
}
|
|
|
|
public void Unbind()
|
|
{
|
|
if (_boundData != null)
|
|
{
|
|
_boundData.OnTypedValueChanged -= OnDataValueChanged;
|
|
_boundData = null;
|
|
}
|
|
}
|
|
|
|
private void OnDataValueChanged(IUTKPropertyItem<Enum> item, Enum oldValue, Enum newValue)
|
|
{
|
|
if (!Equals(_value, newValue))
|
|
{
|
|
_value = newValue;
|
|
UpdateValueUI();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Dispose
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (_disposed) return;
|
|
|
|
if (disposing)
|
|
{
|
|
UnregisterEvents();
|
|
Unbind();
|
|
|
|
OnValueChanged = null;
|
|
_enumDropdown = null;
|
|
_readOnlyField = null;
|
|
}
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
#endregion
|
|
}
|
|
}
|