#nullable enable
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
///
/// 트리 뷰 컴포넌트.
/// Unity TreeView를 래핑하여 커스텀 스타일을 적용합니다.
/// 계층적(부모-자식) 구조의 데이터를 접기/펼치기로 표시합니다.
///
///
/// TreeView(트리 뷰)란?
///
/// TreeView는 계층 구조(부모-자식 관계)를 가진 데이터를 표시하는 UI 컴포넌트입니다.
/// 폴더 구조, 조직도, 메뉴 계층, 게임 오브젝트 계층 등을 표현할 때 사용합니다.
/// 각 노드는 펼치거나 접을 수 있어 복잡한 구조를 효율적으로 탐색할 수 있습니다.
///
///
/// ListView vs TreeView:
///
/// - ListView - 단순 목록 (1차원 데이터)
/// - TreeView - 계층 구조 (부모-자식, 중첩 가능)
///
///
/// TreeViewItemData 구조:
///
/// TreeViewItemData(int id, T data, List> children)
/// - id: 고유 식별자 (필수, 중복 불가)
/// - data: 노드에 저장할 데이터
/// - children: 자식 노드 목록 (없으면 리프 노드)
///
///
/// 필수 설정:
///
/// - SetRootItems() - 루트 노드 설정
/// - makeItem - 항목 VisualElement 생성 함수
/// - bindItem - 데이터를 요소에 바인딩하는 함수
///
///
/// 주요 메서드:
///
/// - SetRootItems() - 전체 트리 데이터 설정
/// - GetItemDataForIndex(index) - 인덱스로 데이터 조회
/// - ExpandItem(id) - 특정 노드 펼치기
/// - CollapseItem(id) - 특정 노드 접기
/// - ExpandAll() - 모든 노드 펼치기
/// - CollapseAll() - 모든 노드 접기
///
///
/// 실제 활용 예시:
///
/// - 파일 탐색기 - 폴더/파일 계층 구조
/// - Unity Hierarchy - 게임 오브젝트 계층
/// - 조직도 - 부서/팀/직원 구조
/// - 메뉴 시스템 - 다단계 메뉴
/// - 카테고리 - 대분류/중분류/소분류
///
///
///
/// C# 코드에서 사용:
///
/// // 트리 뷰 생성
/// var treeView = new UTKTreeView();
/// treeView.fixedItemHeight = 24;
///
/// // 계층 데이터 구성
/// var rootItems = new List>
/// {
/// new TreeViewItemData(0, "프로젝트", new List>
/// {
/// new TreeViewItemData(1, "Assets", new List>
/// {
/// new TreeViewItemData(2, "Scripts"),
/// new TreeViewItemData(3, "Prefabs"),
/// new TreeViewItemData(4, "Materials")
/// }),
/// new TreeViewItemData(5, "Packages")
/// }),
/// new TreeViewItemData(6, "Settings")
/// };
///
/// treeView.SetRootItems(rootItems);
///
/// // 항목 생성 함수
/// treeView.makeItem = () => new Label();
///
/// // 데이터 바인딩 함수
/// treeView.bindItem = (element, index) => {
/// var data = treeView.GetItemDataForIndex(index);
/// (element as Label).text = data;
/// };
///
/// // 선택 이벤트
/// treeView.OnItemSelected += (index) => {
/// var selectedData = treeView.GetItemDataForIndex(index);
/// Debug.Log($"선택됨: {selectedData}");
/// };
///
/// // 더블클릭 이벤트 (폴더 열기 등)
/// treeView.OnItemDoubleClicked += (index) => {
/// var data = treeView.GetItemDataForIndex(index);
/// OpenFolder(data);
/// };
///
/// // 특정 노드 펼치기
/// treeView.ExpandItem(0); // ID 0인 노드 펼치기
///
/// // 모든 노드 펼치기
/// treeView.ExpandAll();
///
/// 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(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 OnSelectionChanged(IEnumerable