#nullable enable
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
///
/// UTKComponentList를 래핑하여 윈도우 형태로 제공하는 컴포넌트입니다.
///
/// 개요:
///
/// UTKComponentListWindow는 UTKComponentList를 내부에 포함하고 헤더(타이틀, 닫기 버튼)를 추가한
/// 윈도우 형태의 컴포넌트입니다. 모든 트리 관련 기능은 내부 UTKComponentList에 위임됩니다.
///
///
/// UXML 사용 예시:
///
///
///
///
/// ]]>
///
/// C# 사용 예시:
/// ("component-window");
///
/// // 2. 윈도우 제목 및 닫기 버튼 설정
/// componentWindow.Title = "모델 리스트";
/// componentWindow.ShowCloseButton = true;
///
/// // 3. 데이터 구성 - 카테고리와 아이템
/// var data = new List
/// {
/// new UTKComponentListCategoryData
/// {
/// name = "캐릭터",
/// isExpanded = true,
/// children = new List
/// {
/// new UTKComponentListItemData
/// {
/// name = "플레이어",
/// ExternalKey = "player_001",
/// IsVisible = true
/// },
/// new UTKComponentListItemData
/// {
/// name = "NPC",
/// ExternalKey = "npc_001",
/// IsVisible = true
/// }
/// }
/// }
/// };
/// componentWindow.SetData(data);
///
/// // 4. 선택 이벤트 구독
/// componentWindow.OnItemSelected = (selectedItems) =>
/// {
/// foreach (var item in selectedItems)
/// {
/// Debug.Log($"선택됨: {item.name}");
/// // 3D 뷰에서 해당 모델 하이라이트
/// HighlightModel(item.ExternalKey);
/// }
/// };
///
/// // 5. 선택 해제 이벤트
/// componentWindow.OnItemDeselected = (deselectedItems) =>
/// {
/// foreach (var item in deselectedItems)
/// {
/// UnhighlightModel(item.ExternalKey);
/// }
/// };
///
/// // 6. 가시성 변경 이벤트 (눈 아이콘)
/// componentWindow.OnItemVisibilityChanged += (item, isVisible) =>
/// {
/// var gameObject = FindGameObjectByKey(item.ExternalKey);
/// if (gameObject != null)
/// {
/// gameObject.SetActive(isVisible);
/// }
/// };
///
/// // 7. 삭제 이벤트 (Delete/Backspace 키)
/// componentWindow.EnabledDeleteItem = true;
/// componentWindow.OnItemDeleted = (item) =>
/// {
/// Debug.Log($"삭제 요청: {item.name}");
/// componentWindow.DeleteItem(item);
/// };
///
/// // 8. 더블클릭 이벤트
/// componentWindow.OnItemDoubleClicked = (item) =>
/// {
/// // 카메라 포커스
/// FocusCameraOn(item.ExternalKey);
/// };
///
/// // 9. 윈도우 닫힘 이벤트
/// componentWindow.OnClosed += () =>
/// {
/// Debug.Log("윈도우가 닫혔습니다.");
/// };
///
/// // 10. 프로그래밍 방식 선택
/// componentWindow.SelectItem("플레이어", notify: true);
/// componentWindow.DeselectItem("플레이어", notify: false);
/// componentWindow.ClearSelection();
/// componentWindow.SelectByItemId(itemId);
///
/// // 11. 아이템 추가/삭제
/// var newItem = new UTKComponentListItemData { name = "새 캐릭터" };
/// componentWindow.AddItem(newItem);
/// componentWindow.AddItem(categoryData, newItem);
/// componentWindow.DeleteItem(newItem);
/// componentWindow.SetItemName(newItem, "수정된 이름");
///
/// // 12. 윈도우 표시
/// componentWindow.Show();
///
/// // 13. 리소스 해제 (OnDestroy에서 호출)
/// componentWindow.Dispose();
/// ]]>
///
[UxmlElement]
public partial class UTKComponentListWindow : VisualElement, IDisposable
{
#region IDisposable
private bool _disposed = false;
#endregion
#region 상수 (Constants)
/// 메인 UXML 파일 경로 (Resources 폴더 기준)
private const string UXML_PATH = "UIToolkit/Window/UTKComponentListWindow";
/// USS 파일 경로 (Resources 폴더 기준)
private const string USS_PATH = "UIToolkit/Window/UTKComponentListWindowUss";
#endregion
#region UI 컴포넌트 참조 (UI Component References)
/// 내부 UTKComponentList 컴포넌트
private UTKComponentList? _componentList;
/// 트리 리스트 닫기 버튼 (UTKButton)
private UTKButton? _closeButton;
/// 윈도우 제목 라벨
private Label? _titleLabel;
#endregion
#region 공개 속성 (Public Properties)
///
/// 항목 삭제 기능 활성화 여부입니다.
/// true일 때만 Delete/Backspace 키로 항목 삭제 이벤트가 발생합니다.
/// 기본값은 false입니다.
///
public bool EnabledDeleteItem
{
get => _componentList?.EnabledDeleteItem ?? false;
set { if (_componentList != null) _componentList.EnabledDeleteItem = value; }
}
/// 윈도우 제목을 가져오거나 설정합니다.
public string Title
{
get => _titleLabel?.text ?? string.Empty;
set { if (_titleLabel != null) _titleLabel.text = value; }
}
/// 닫기 버튼 표시 여부를 설정합니다.
public bool ShowCloseButton
{
get => _closeButton?.style.display == DisplayStyle.Flex;
set { if (_closeButton != null) _closeButton.style.display = value ? DisplayStyle.Flex : DisplayStyle.None; }
}
#endregion
#region 외부 이벤트 (Public Events)
///
/// 메인/검색 리스트에서 항목이 선택될 때 발생합니다.
///
public Action>? OnItemSelected
{
get => _componentList?.OnItemSelected;
set { if (_componentList != null) _componentList.OnItemSelected = value; }
}
///
/// 메인/검색 리스트에서 항목이 선택 해제될 때 발생합니다.
///
public Action>? OnItemDeselected
{
get => _componentList?.OnItemDeselected;
set { if (_componentList != null) _componentList.OnItemDeselected = value; }
}
///
/// 항목의 가시성(눈 아이콘)이 변경될 때 발생합니다.
///
public event Action? OnItemVisibilityChanged
{
add { if (_componentList != null) _componentList.OnItemVisibilityChanged += value; }
remove { if (_componentList != null) _componentList.OnItemVisibilityChanged -= value; }
}
///
/// 메인/검색 리스트에서 항목이 삭제될 때 발생합니다 (Delete 키).
///
public Action? OnItemDeleted
{
get => _componentList?.OnItemDeleted;
set { if (_componentList != null) _componentList.OnItemDeleted = value; }
}
///
/// 메인/검색 리스트에서 항목이 더블클릭될 때 발생합니다.
///
public Action? OnItemDoubleClicked
{
get => _componentList?.OnItemDoubleClicked;
set { if (_componentList != null) _componentList.OnItemDoubleClicked = value; }
}
///
/// 아이콘을 클릭할 때 발생합니다.
///
public Action? OnItemIconClicked
{
get => _componentList?.OnItemIconClicked;
set { if (_componentList != null) _componentList.OnItemIconClicked = value; }
}
///
/// 트리 리스트가 닫힐 때(숨겨질 때) 발생합니다.
/// 닫기 버튼 클릭 시 트리거됩니다.
///
public event Action? OnClosed;
#endregion
#region 생성자 (Constructor)
///
/// UTKComponentListWindow 컴포넌트를 초기화합니다.
/// UXML 템플릿을 로드하고 내부 UTKComponentList를 설정합니다.
///
public UTKComponentListWindow()
{
// 1. 메인 UXML 로드 및 복제
var visualTree = Resources.Load(UXML_PATH);
if (visualTree == null)
{
Debug.LogError($"[UTKComponentListWindow] UXML not found at: {UXML_PATH}");
return;
}
visualTree.CloneTree(this);
// 2. 내부 UTKComponentList 찾기 (UXML의 ui:Instance로 생성된 컴포넌트)
_componentList = this.Q();
if (_componentList == null)
{
Debug.LogError("[UTKComponentListWindow] UTKComponentList not found in UXML");
return;
}
// 3. 테마 적용 및 변경 구독
UTKThemeManager.Instance.ApplyThemeToElement(this);
SubscribeToThemeChanges();
// USS 로드 (테마 변수 스타일시트 이후에 로드되어야 변수가 해석됨)
var uss = Resources.Load(USS_PATH);
if (uss != null)
{
styleSheets.Add(uss);
}
// 4. 헤더 요소 참조
_titleLabel = this.Q