Files
XRLib/Assets/Scripts/UVC/UIToolkit/Property/Views/UTKPropertyItemViewFactory.cs
2026-02-04 20:31:52 +09:00

216 lines
9.3 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
/// <summary>
/// PropertyItem 데이터에 해당하는 View를 생성하는 팩토리 클래스입니다.
///
/// <para><b>주요 기능:</b></para>
/// <list type="bullet">
/// <item>PropertyType에 따라 적절한 View 인스턴스 생성</item>
/// <item>Data 클래스와 View 자동 바인딩</item>
/// <item>커스텀 View 등록 지원</item>
/// </list>
///
/// <para><b>사용법:</b></para>
/// <code>
/// var data = new UTKFloatPropertyItem("speed", "속도", 1.5f);
/// var view = UTKPropertyItemViewFactory.CreateView(data);
/// parent.Add(view);
/// </code>
/// </summary>
public static class UTKPropertyItemViewFactory
{
#region Fields
private static readonly Dictionary<UTKPropertyType, Func<IUTKPropertyItemView>> _customViewFactories = new();
#endregion
#region Public Methods
/// <summary>
/// PropertyItem 데이터에 해당하는 View를 생성하고 바인딩합니다.
/// </summary>
/// <param name="data">PropertyItem 데이터</param>
/// <returns>바인딩된 View (VisualElement)</returns>
public static VisualElement CreateView(IUTKPropertyItem data)
{
var view = CreateViewInstance(data);
view.Bind(data);
if (view is VisualElement element)
{
return element;
}
Debug.LogError($"[UTKPropertyItemViewFactory] View is not a VisualElement: {view.GetType().Name}");
return new VisualElement();
}
/// <summary>
/// PropertyItem 데이터에 해당하는 View를 생성합니다 (바인딩 없음).
/// </summary>
/// <param name="data">PropertyItem 데이터 (View 설정에 필요한 정보 제공)</param>
/// <returns>View 인스턴스</returns>
public static IUTKPropertyItemView CreateViewInstance(IUTKPropertyItem data)
{
// 커스텀 팩토리 우선
if (_customViewFactories.TryGetValue(data.PropertyType, out var customFactory))
{
return customFactory();
}
// 기본 View 생성 - View의 Bind 메서드에서 데이터 속성 동기화 처리
return data.PropertyType switch
{
UTKPropertyType.String => CreateStringView(data),
UTKPropertyType.Int => CreateIntView(data),
UTKPropertyType.Float => CreateFloatView(data),
UTKPropertyType.Bool => new UTKBoolPropertyItemView(),
UTKPropertyType.Vector2 => new UTKVector2PropertyItemView(),
UTKPropertyType.Vector3 => new UTKVector3PropertyItemView(),
UTKPropertyType.Color => new UTKColorPropertyItemView(),
UTKPropertyType.Date => new UTKDatePropertyItemView(),
UTKPropertyType.DateTime => new UTKDateTimePropertyItemView(),
UTKPropertyType.Enum => CreateEnumView(data),
UTKPropertyType.DropdownList => CreateDropdownView(data),
UTKPropertyType.RadioGroup => CreateRadioView(data),
UTKPropertyType.IntRange => new UTKIntRangePropertyItemView(),
UTKPropertyType.FloatRange => new UTKFloatRangePropertyItemView(),
UTKPropertyType.DateRange => new UTKDateRangePropertyItemView(),
UTKPropertyType.DateTimeRange => new UTKDateTimeRangePropertyItemView(),
UTKPropertyType.ColorState => new UTKColorStatePropertyItemView(),
_ => throw new ArgumentException($"Unknown property type: {data.PropertyType}")
};
}
/// <summary>
/// PropertyType에 해당하는 빈 View 인스턴스를 생성합니다.
/// </summary>
/// <param name="propertyType">속성 타입</param>
/// <returns>View 인스턴스</returns>
public static IUTKPropertyItemView CreateViewInstance(UTKPropertyType propertyType)
{
// 커스텀 팩토리 우선
if (_customViewFactories.TryGetValue(propertyType, out var customFactory))
{
return customFactory();
}
return propertyType switch
{
UTKPropertyType.String => new UTKStringPropertyItemView(),
UTKPropertyType.Int => new UTKIntPropertyItemView(),
UTKPropertyType.Float => new UTKFloatPropertyItemView(),
UTKPropertyType.Bool => new UTKBoolPropertyItemView(),
UTKPropertyType.Vector2 => new UTKVector2PropertyItemView(),
UTKPropertyType.Vector3 => new UTKVector3PropertyItemView(),
UTKPropertyType.Color => new UTKColorPropertyItemView(),
UTKPropertyType.Date => new UTKDatePropertyItemView(),
UTKPropertyType.DateTime => new UTKDateTimePropertyItemView(),
UTKPropertyType.Enum => new UTKEnumPropertyItemView(),
UTKPropertyType.DropdownList => new UTKDropdownPropertyItemView(),
UTKPropertyType.RadioGroup => new UTKRadioPropertyItemView(),
UTKPropertyType.IntRange => new UTKIntRangePropertyItemView(),
UTKPropertyType.FloatRange => new UTKFloatRangePropertyItemView(),
UTKPropertyType.DateRange => new UTKDateRangePropertyItemView(),
UTKPropertyType.DateTimeRange => new UTKDateTimeRangePropertyItemView(),
UTKPropertyType.ColorState => new UTKColorStatePropertyItemView(),
_ => throw new ArgumentException($"Unknown property type: {propertyType}")
};
}
/// <summary>
/// 커스텀 View 팩토리를 등록합니다.
/// </summary>
/// <param name="propertyType">속성 타입</param>
/// <param name="factory">View 생성 팩토리 함수</param>
public static void RegisterCustomView(UTKPropertyType propertyType, Func<IUTKPropertyItemView> factory)
{
_customViewFactories[propertyType] = factory;
}
/// <summary>
/// 커스텀 View 팩토리를 제거합니다.
/// </summary>
/// <param name="propertyType">속성 타입</param>
public static void UnregisterCustomView(UTKPropertyType propertyType)
{
_customViewFactories.Remove(propertyType);
}
/// <summary>
/// 모든 커스텀 View 팩토리를 제거합니다.
/// </summary>
public static void ClearCustomViews()
{
_customViewFactories.Clear();
}
#endregion
#region Private Methods
private static IUTKPropertyItemView CreateStringView(IUTKPropertyItem data)
{
// UTKStringPropertyItem의 Multiline 속성에 따라 View 생성
if (data is UTKStringPropertyItem stringItem)
{
return new UTKStringPropertyItemView(stringItem.Id, stringItem.Value ?? "", stringItem.IsMultiline, stringItem.MaxLength, stringItem.IsReadOnly);
}
return new UTKStringPropertyItemView();
}
private static IUTKPropertyItemView CreateIntView(IUTKPropertyItem data)
{
// UTKIntPropertyItem의 UseSlider 속성에 따라 View 생성
if (data is UTKIntPropertyItem intItem && intItem.UseSlider)
{
return new UTKIntPropertyItemView("", intItem.Value, intItem.MinValue, intItem.MaxValue, true);
}
return new UTKIntPropertyItemView();
}
private static IUTKPropertyItemView CreateFloatView(IUTKPropertyItem data)
{
// UTKFloatPropertyItem의 UseSlider 속성에 따라 View 생성
if (data is UTKFloatPropertyItem floatItem && floatItem.UseSlider)
{
return new UTKFloatPropertyItemView("", floatItem.Value, floatItem.MinValue, floatItem.MaxValue, true);
}
return new UTKFloatPropertyItemView();
}
private static IUTKPropertyItemView CreateEnumView(IUTKPropertyItem data)
{
// UTKEnumPropertyItem의 Value로 EnumDropDown 초기화
if (data is UTKEnumPropertyItem enumItem && enumItem.Value != null)
{
return new UTKEnumPropertyItemView("", enumItem.Value);
}
return new UTKEnumPropertyItemView();
}
private static IUTKPropertyItemView CreateDropdownView(IUTKPropertyItem data)
{
// UTKDropdownPropertyItem의 Choices로 Dropdown 초기화
if (data is UTKDropdownPropertyItem dropdownItem)
{
return new UTKDropdownPropertyItemView("", dropdownItem.Choices);
}
return new UTKDropdownPropertyItemView();
}
private static IUTKPropertyItemView CreateRadioView(IUTKPropertyItem data)
{
// UTKRadioPropertyItem의 Choices로 RadioGroup 초기화
if (data is UTKRadioPropertyItem radioItem)
{
return new UTKRadioPropertyItemView("", radioItem.Choices);
}
return new UTKRadioPropertyItemView();
}
#endregion
}
}