Files
XRLib/Assets/Scripts/UVC/UIToolkit/Common/UTKFoldout.cs
2026-01-13 20:39:45 +09:00

137 lines
3.7 KiB
C#

#nullable enable
using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
/// <summary>
/// 접을 수 있는 섹션 컴포넌트.
/// Unity Foldout을 래핑하여 커스텀 스타일을 적용합니다.
/// </summary>
/// <example>
/// <para><b>C# 코드에서 사용:</b></para>
/// <code>
/// // 기본 폴드아웃
/// var foldout = new UTKFoldout("고급 설정", expanded: false);
/// foldout.Add(new Label("옵션 1"));
/// foldout.Add(new Label("옵션 2"));
///
/// // 상태 변경 이벤트
/// foldout.OnValueChanged += (isExpanded) => {
/// Debug.Log(isExpanded ? "펼쳐짐" : "접힘");
/// };
///
/// // 프로그래밍 방식으로 상태 제어
/// foldout.IsExpanded = true;
/// </code>
/// <para><b>UXML에서 사용:</b></para>
/// <code>
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
/// <!-- 기본 폴드아웃 -->
/// <utk:UTKFoldout text="설정" value="true">
/// <ui:Label text="내용 1" />
/// <ui:Label text="내용 2" />
/// </utk:UTKFoldout>
///
/// <!-- 접힌 상태 -->
/// <utk:UTKFoldout text="고급 옵션" value="false">
/// <ui:Label text="숨겨진 내용" />
/// </utk:UTKFoldout>
/// </ui:UXML>
/// </code>
/// </example>
[UxmlElement]
public partial class UTKFoldout : Foldout, IDisposable
{
#region Constants
private const string USS_PATH = "UIToolkit/Common/UTKFoldout";
#endregion
#region Fields
private bool _disposed;
#endregion
#region Events
/// <summary>펼침/접힘 상태 변경 이벤트</summary>
public event Action<bool>? OnValueChanged;
#endregion
#region Properties
/// <summary>펼침 상태</summary>
public bool IsExpanded
{
get => value;
set => this.value = value;
}
#endregion
#region Constructor
public UTKFoldout() : base()
{
UTKThemeManager.Instance.ApplyThemeToElement(this);
var uss = Resources.Load<StyleSheet>(USS_PATH);
if (uss != null)
{
styleSheets.Add(uss);
}
SetupStyles();
SetupEvents();
SubscribeToThemeChanges();
}
public UTKFoldout(string title, bool expanded = true) : this()
{
text = title;
value = expanded;
}
#endregion
#region Setup
private void SetupStyles()
{
AddToClassList("utk-foldout");
}
private void SetupEvents()
{
this.RegisterValueChangedCallback(OnFoldoutValueChanged);
}
private void SubscribeToThemeChanges()
{
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
RegisterCallback<DetachFromPanelEvent>(_ =>
{
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
});
}
private void OnThemeChanged(UTKTheme theme)
{
UTKThemeManager.Instance.ApplyThemeToElement(this);
}
#endregion
#region Event Handlers
private void OnFoldoutValueChanged(ChangeEvent<bool> evt)
{
OnValueChanged?.Invoke(evt.newValue);
}
#endregion
#region IDisposable
public void Dispose()
{
if (_disposed) return;
_disposed = true;
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
OnValueChanged = null;
}
#endregion
}
}