Files
XRLib/Assets/Scripts/UVC/UIToolkit/Property/Views/UTKEnumPropertyItemView.cs

268 lines
7.1 KiB
C#
Raw Normal View History

2026-02-04 20:31:52 +09:00
#nullable enable
using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
/// <summary>
/// Enum 속성 View 클래스입니다.
/// UTKEnumDropDown을 사용하여 열거형 값을 표시/편집합니다.
/// </summary>
[UxmlElement]
public partial class UTKEnumPropertyItemView : UTKPropertyItemViewBase, IUTKPropertyItemView<Enum>
{
#region Fields
private UTKEnumDropDown? _enumDropdown;
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()
{
_enumDropdown = this.Q<UTKEnumDropDown>("enum-dropdown");
// Fallback: UXML에서 못 찾으면 생성
if (_valueContainer != null && _enumDropdown == null)
{
_enumDropdown = new UTKEnumDropDown { name = "enum-dropdown" };
_enumDropdown.AddToClassList("utk-property-item-view__dropdown");
_valueContainer.Add(_enumDropdown);
}
// 초기 값 설정
if (_enumDropdown != null)
{
if (_value != null)
{
_enumDropdown.Init(_value);
}
_enumDropdown.IsEnabled = !IsReadOnly;
}
}
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 (_enumDropdown != null)
{
_enumDropdown.IsEnabled = !isReadOnly;
}
}
#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 (_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;
}
base.Dispose(disposing);
}
#endregion
}
}