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

164 lines
4.7 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
/// <summary>
/// 토글 버튼 그룹 컴포넌트.
/// Unity ToggleButtonGroup을 래핑하여 커스텀 스타일을 적용합니다.
/// </summary>
/// <example>
/// <para><b>C# 코드에서 사용:</b></para>
/// <code>
/// // 토글 버튼 그룹 생성
/// var group = new UTKToggleButtonGroup();
/// group.Add(new Button { text = "왼쪽" });
/// group.Add(new Button { text = "가운데" });
/// group.Add(new Button { text = "오른쪽" });
///
/// // 단일 선택 모드
/// group.allowEmptySelection = false;
///
/// // 다중 선택 모드
/// group.isMultipleSelection = true;
///
/// // 선택 변경 이벤트
/// group.OnSelectionChanged += (indices) => {
/// Debug.Log($"선택됨: {string.Join(", ", indices)}");
/// };
/// </code>
/// <para><b>UXML에서 사용:</b></para>
/// <code>
/// <ui:UXML xmlns:utk="UVC.UIToolkit">
/// <utk:UTKToggleButtonGroup allow-empty-selection="false">
/// <ui:Button text="왼쪽" />
/// <ui:Button text="가운데" />
/// <ui:Button text="오른쪽" />
/// </utk:UTKToggleButtonGroup>
/// </ui:UXML>
/// </code>
/// </example>
[UxmlElement]
public partial class UTKToggleButtonGroup : ToggleButtonGroup, IDisposable
{
#region Constants
private const string USS_PATH = "UIToolkit/Button/UTKToggleButtonGroup";
#endregion
#region Fields
private bool _disposed;
private bool _isEnabled = true;
#endregion
#region Events
/// <summary>선택 변경 이벤트</summary>
public event Action<IEnumerable<int>>? OnSelectionChanged;
#endregion
#region Properties
/// <summary>활성화 상태</summary>
[UxmlAttribute]
public bool IsEnabled
{
get => _isEnabled;
set
{
_isEnabled = value;
SetEnabled(value);
EnableInClassList("utk-toggle-group--disabled", !value);
}
}
#endregion
#region Constructor
public UTKToggleButtonGroup() : base()
{
UTKThemeManager.Instance.ApplyThemeToElement(this);
var uss = Resources.Load<StyleSheet>(USS_PATH);
if (uss != null)
{
styleSheets.Add(uss);
}
SetupStyles();
SetupEvents();
SubscribeToThemeChanges();
}
#endregion
#region Setup
private void SetupStyles()
{
AddToClassList("utk-toggle-group");
}
private void SetupEvents()
{
this.RegisterValueChangedCallback(OnValueChanged);
}
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 OnValueChanged(ChangeEvent<ToggleButtonGroupState> evt)
{
var state = evt.newValue;
var buffer = new int[state.length];
var activeOptions = state.GetActiveOptions(buffer);
var result = new List<int>();
foreach (var idx in activeOptions)
{
result.Add(idx);
}
OnSelectionChanged?.Invoke(result);
}
#endregion
#region Methods
/// <summary>
/// 토글 버튼 추가
/// </summary>
public void AddButton(string text, string? icon = null)
{
var button = new Button { text = text };
button.AddToClassList("utk-toggle-group__button");
if (!string.IsNullOrEmpty(icon))
{
var iconLabel = new Label(icon);
iconLabel.AddToClassList("utk-toggle-group__icon");
button.Insert(0, iconLabel);
}
Add(button);
}
#endregion
#region IDisposable
public void Dispose()
{
if (_disposed) return;
_disposed = true;
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
OnSelectionChanged = null;
}
#endregion
}
}