Files
EnglewoodLAB/Assets/Scripts/UVC/UIToolkit/Property/Views/UTKPropertyItemViewFactory.cs

286 lines
13 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.MultiSelectDropdownList => CreateMultiSelectDropdownView(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(),
UTKPropertyType.FloatDropdown => CreateFloatDropdownView(data),
UTKPropertyType.Button => CreateButtonView(data),
_ => 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.MultiSelectDropdownList => new UTKMultiSelectDropdownPropertyItemView(),
UTKPropertyType.RadioGroup => new UTKRadioPropertyItemView(),
UTKPropertyType.IntRange => new UTKIntRangePropertyItemView(),
UTKPropertyType.FloatRange => new UTKFloatRangePropertyItemView(),
UTKPropertyType.DateRange => new UTKDateRangePropertyItemView(),
UTKPropertyType.DateTimeRange => new UTKDateTimeRangePropertyItemView(),
UTKPropertyType.ColorState => new UTKColorStatePropertyItemView(),
UTKPropertyType.FloatDropdown => new UTKFloatDropdownPropertyItemView(),
UTKPropertyType.Button => new UTKButtonItemView(),
_ => throw new ArgumentException($"Unknown property type: {propertyType}")
};
}
/// <summary>
/// PropertyItem 데이터에 해당하는 View의 Type을 반환합니다.
/// View 재사용 시 기존 View와 타입 호환 여부 확인에 사용합니다.
/// </summary>
/// <param name="data">PropertyItem 데이터</param>
/// <returns>View Type</returns>
public static Type GetViewType(IUTKPropertyItem data)
{
return data.PropertyType switch
{
UTKPropertyType.String => typeof(UTKStringPropertyItemView),
UTKPropertyType.Int => typeof(UTKIntPropertyItemView),
UTKPropertyType.Float => typeof(UTKFloatPropertyItemView),
UTKPropertyType.Bool => typeof(UTKBoolPropertyItemView),
UTKPropertyType.Vector2 => typeof(UTKVector2PropertyItemView),
UTKPropertyType.Vector3 => typeof(UTKVector3PropertyItemView),
UTKPropertyType.Color => typeof(UTKColorPropertyItemView),
UTKPropertyType.Date => typeof(UTKDatePropertyItemView),
UTKPropertyType.DateTime => typeof(UTKDateTimePropertyItemView),
UTKPropertyType.Enum => typeof(UTKEnumPropertyItemView),
UTKPropertyType.DropdownList => typeof(UTKDropdownPropertyItemView),
UTKPropertyType.MultiSelectDropdownList => typeof(UTKMultiSelectDropdownPropertyItemView),
UTKPropertyType.RadioGroup => typeof(UTKRadioPropertyItemView),
UTKPropertyType.IntRange => typeof(UTKIntRangePropertyItemView),
UTKPropertyType.FloatRange => typeof(UTKFloatRangePropertyItemView),
UTKPropertyType.DateRange => typeof(UTKDateRangePropertyItemView),
UTKPropertyType.DateTimeRange => typeof(UTKDateTimeRangePropertyItemView),
UTKPropertyType.ColorState => typeof(UTKColorStatePropertyItemView),
UTKPropertyType.FloatDropdown => typeof(UTKFloatDropdownPropertyItemView),
UTKPropertyType.Button => typeof(UTKButtonItemView),
_ => typeof(VisualElement)
};
}
/// <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();
}
private static IUTKPropertyItemView CreateMultiSelectDropdownView(IUTKPropertyItem data)
{
// UTKMultiSelectDropdownPropertyItem의 Choices로 MultiSelectDropdown 초기화
if (data is UTKMultiSelectDropdownPropertyItem multiSelectItem)
{
return new UTKMultiSelectDropdownPropertyItemView("", multiSelectItem.Choices);
}
return new UTKMultiSelectDropdownPropertyItemView();
}
private static IUTKPropertyItemView CreateFloatDropdownView(IUTKPropertyItem data)
{
// UTKFloatDropdownPropertyItem의 Choices로 View 초기화
if (data is UTKFloatDropdownPropertyItem floatDropdownItem)
{
return new UTKFloatDropdownPropertyItemView(floatDropdownItem);
}
return new UTKFloatDropdownPropertyItemView();
}
private static IUTKPropertyItemView CreateButtonView(IUTKPropertyItem data)
{
// UTKButtonItem으로 ButtonView 초기화
if (data is UTKButtonItem buttonItem)
{
return new UTKButtonItemView(buttonItem);
}
return new UTKButtonItemView();
}
#endregion
}
}