#nullable enable using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// 설정 표시 정보 아이템 데이터. /// public class ReordableListItemData { /// 표시 순서 (ListView 인덱스 기준) public int Order { get; set; } /// 사용 유무 public bool IsActive { get; set; } /// 표시 내용 public string DisplayText { get; set; } = ""; } /// /// 설정 표시 정보 탭 뷰. /// UTKListView를 활용하여 마우스 드래그로 항목 순서를 변경할 수 있는 설정 목록 뷰입니다. /// 각 항목은 드래그 핸들, 체크박스(사용 유무), 입력 필드(내용 수정)로 구성됩니다. /// [UxmlElement] public partial class UTKReordableList : VisualElement, IDisposable { #region Constants private const string USS_PATH = "UIToolkit/List/UTKReordableListUss"; private const string ITEM_UXML_PATH = "UIToolkit/List/UTKReordableListItem"; private const string ITEM_USS_PATH = "UIToolkit/List/UTKReordableListItemUss"; private const float ITEM_HEIGHT = 36f; #endregion #region Fields private bool _disposed; private UTKListView? _listView; private List _items = new(); private VisualTreeAsset? _itemTemplate; private StyleSheet? _itemStyleSheet; #endregion #region Events /// 순서 변경 시 발생 public event Action? OnOrderChanged; /// 데이터(체크/텍스트) 변경 시 발생 public event Action? OnDataChanged; #endregion #region Constructor public UTKReordableList() : 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(); } #endregion #region Setup private void CreateUI() { AddToClassList("reordable-list"); SetupListView(); } private void SetupListView() { _listView = new UTKListView(); _listView.makeItem = MakeItem; _listView.bindItem = BindItem; _listView.unbindItem = UnbindItem; _listView.fixedItemHeight = ITEM_HEIGHT; _listView.selectionType = SelectionType.Single; _listView.reorderable = true; _listView.reorderMode = ListViewReorderMode.Animated; _listView.itemIndexChanged += OnItemIndexChanged; Add(_listView); } 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 ListView Callbacks private VisualElement MakeItem() { // UXML 캐싱 _itemTemplate ??= Resources.Load(ITEM_UXML_PATH); // USS 캐싱 (코드에서 로드 - UXML에서 지정하지 않음) _itemStyleSheet ??= Resources.Load(ITEM_USS_PATH); if (_itemTemplate != null) { var root = _itemTemplate.Instantiate(); // USS 적용 (코드에서 적용) if (_itemStyleSheet != null) root.styleSheets.Add(_itemStyleSheet); // 드래그 핸들 아이콘 설정 var handle = root.Q