#nullable enable using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// 트리 뷰 컴포넌트. /// Unity TreeView를 래핑하여 커스텀 스타일을 적용합니다. /// /// /// C# 코드에서 사용: /// /// // 트리 뷰 생성 /// var treeView = new UTKTreeView(); /// /// // 데이터 구조 설정 /// var rootItems = new List> { /// new TreeViewItemData(0, "루트 1", new List> { /// new TreeViewItemData(1, "자식 1-1"), /// new TreeViewItemData(2, "자식 1-2") /// }), /// new TreeViewItemData(3, "루트 2") /// }; /// treeView.SetRootItems(rootItems); /// /// // 아이템 렌더링 /// treeView.makeItem = () => new Label(); /// treeView.bindItem = (element, index) => { /// var item = treeView.GetItemDataForIndex(index); /// (element as Label).text = item; /// }; /// /// // 선택 이벤트 /// treeView.OnItemSelected += (index) => Debug.Log($"선택: {index}"); /// /// UXML에서 사용: /// /// /// /// /// /// [UxmlElement] public partial class UTKTreeView : TreeView, IDisposable { #region Constants private const string USS_PATH = "UIToolkit/List/UTKTreeView"; #endregion #region Fields private bool _disposed; #endregion #region Events /// 아이템 선택 이벤트 public event Action? OnItemSelected; /// 아이템 더블클릭 이벤트 public event Action? OnItemDoubleClicked; #endregion #region Constructor public UTKTreeView() : 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-treeview"); } private void SetupEvents() { selectionChanged += OnSelectionChanged; itemsChosen += OnItemsChosen; } private void SubscribeToThemeChanges() { UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged; RegisterCallback(_ => { UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; }); } private void OnThemeChanged(UTKTheme theme) { UTKThemeManager.Instance.ApplyThemeToElement(this); } #endregion #region Event Handlers private void OnSelectionChanged(IEnumerable items) { OnItemSelected?.Invoke(selectedIndex); } private void OnItemsChosen(IEnumerable items) { OnItemDoubleClicked?.Invoke(selectedIndex); } #endregion #region IDisposable public void Dispose() { if (_disposed) return; _disposed = true; selectionChanged -= OnSelectionChanged; itemsChosen -= OnItemsChosen; UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; OnItemSelected = null; OnItemDoubleClicked = null; } #endregion } }