#nullable enable using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// 토글 버튼 그룹 컴포넌트. /// Unity ToggleButtonGroup을 래핑하여 커스텀 스타일을 적용합니다. /// /// /// C# 코드에서 사용: /// /// // 토글 버튼 그룹 생성 /// 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)}"); /// }; /// /// UXML에서 사용: /// /// /// /// /// /// /// /// /// /// [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 /// 선택 변경 이벤트 public event Action>? OnSelectionChanged; #endregion #region Properties /// 활성화 상태 [UxmlAttribute("is-enabled")] 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(USS_PATH); if (uss != null) { styleSheets.Add(uss); } SetupStyles(); SetupEvents(); SubscribeToThemeChanges(); } #endregion #region Setup private void SetupStyles() { AddToClassList("utk-toggle-group"); } private void SetupEvents() { RegisterCallback>(OnValueChanged); } private void SubscribeToThemeChanges() { UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged; RegisterCallback(OnAttachToPanelForTheme); RegisterCallback(OnDetachFromPanelForTheme); } private void OnAttachToPanelForTheme(AttachToPanelEvent evt) { UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged; UTKThemeManager.Instance.ApplyThemeToElement(this); } private void OnDetachFromPanelForTheme(DetachFromPanelEvent evt) { UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; } private void OnThemeChanged(UTKTheme theme) { UTKThemeManager.Instance.ApplyThemeToElement(this); } #endregion #region Event Handlers private void OnValueChanged(ChangeEvent evt) { var state = evt.newValue; var buffer = new int[state.length]; var activeOptions = state.GetActiveOptions(buffer); var result = new List(); foreach (var idx in activeOptions) { result.Add(idx); } OnSelectionChanged?.Invoke(result); } #endregion #region Methods /// /// 토글 버튼 추가 /// 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; UnregisterCallback(OnAttachToPanelForTheme); UnregisterCallback(OnDetachFromPanelForTheme); OnSelectionChanged = null; UnregisterCallback>(OnValueChanged); } #endregion } }