#nullable enable using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// 설정 표시 정보 탭 뷰. /// UTKReordableList를 사용하여 표시 항목의 순서, 사용 유무, 내용을 관리합니다. /// [UxmlElement] public partial class UTKSettingDisplayInfoTabView : VisualElement, IDisposable { #region Constants private const string USS_PATH = "UIToolkit/Modal/Setting/UTKSettingDisplayInfoTabViewUss"; #endregion #region Fields private bool _disposed; private UTKReordableList? _reordableList; #endregion #region Events /// 순서 변경 시 발생 public event Action? OnOrderChanged; /// 데이터(체크/텍스트) 변경 시 발생 public event Action? OnDataChanged; #endregion #region Constructor public UTKSettingDisplayInfoTabView() : base() { // 1. 테마 적용 UTKThemeManager.Instance.ApplyThemeToElement(this); // 2. USS 로드 var uss = Resources.Load(USS_PATH); if (uss != null) { styleSheets.Add(uss); } // 3. UI 생성 CreateUI(); // 4. 테마 변경 구독 SubscribeToThemeChanges(); SampleSetAndGetWithDictionary(); } #endregion #region Setup private void CreateUI() { AddToClassList("setting-display-tab-view"); _reordableList = new UTKReordableList(); _reordableList.style.flexGrow = 1; _reordableList.OnOrderChanged += () => OnOrderChanged?.Invoke(); _reordableList.OnDataChanged += () => OnDataChanged?.Invoke(); Add(_reordableList); // 하단 버튼 영역 var buttonContainer = new VisualElement(); buttonContainer.style.flexDirection = FlexDirection.Row; buttonContainer.style.justifyContent = Justify.FlexEnd; buttonContainer.style.paddingTop = 8; var saveBtn = new UTKButton("저장", variant: UTKButton.ButtonVariant.Primary); saveBtn.OnClicked += OnSaveButtonClicked; buttonContainer.Add(saveBtn); Add(buttonContainer); } private void OnSaveButtonClicked() { List> result = ToDictionary(); foreach (var dict in result) { Debug.Log($"order={dict["order"]}, active={dict["active"]}, text={dict["text"]}"); } } 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 Public API /// /// 데이터를 설정하고 리스트를 갱신합니다. /// /// 표시할 아이템 데이터 목록. public void SetData(List items) { _reordableList?.SetData(items); } /// /// List로부터 데이터를 변환하여 설정합니다. /// Dictionary 키: "order" (순서), "active" (사용 유무), "text" (표시 내용) /// /// 변환할 Dictionary 목록. public void SetData(List> listDict) { _reordableList?.SetData(listDict); } /// /// Order 값이 동기화된 데이터 목록을 반환합니다. /// /// 현재 리스트 순서가 반영된 데이터 목록. public List GetData() { return _reordableList?.GetData() ?? new List(); } /// /// 전체 아이템을 List>로 변환하여 반환합니다. /// Dictionary 키: "order" (순서), "active" (사용 유무), "text" (표시 내용) /// /// 각 아이템을 Dictionary로 변환한 목록. public List> ToDictionary() { return _reordableList?.ToDictionary() ?? new List>(); } #endregion #region Sample /// /// Dictionary 기반 데이터 설정 및 조회 샘플. /// public void SampleSetAndGetWithDictionary() { // 1. Dictionary 데이터로 설정 var listDict = new List> { new() { ["order"] = "0", ["active"] = "True", ["text"] = "온도" }, new() { ["order"] = "1", ["active"] = "False", ["text"] = "습도" }, new() { ["order"] = "2", ["active"] = "True", ["text"] = "압력" }, }; SetData(listDict); } #endregion #region IDisposable public void Dispose() { if (_disposed) return; _disposed = true; // 테마 구독 해제 UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; UnregisterCallback(OnAttachToPanelForTheme); UnregisterCallback(OnDetachFromPanelForTheme); // ReordableList 정리 _reordableList?.Dispose(); _reordableList = null; // 이벤트 정리 OnOrderChanged = null; OnDataChanged = null; } #endregion } }