#nullable enable using System; using System.Collections.Generic; using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UIElements; using UVC.Locale; namespace UVC.UIToolkit { /// /// UIToolkit 기반 툴팁 매니저. /// VisualElement에 마우스 오버 시 툴팁을 표시하는 싱글톤 관리자입니다. /// /// /// Tooltip(툴팁)이란? /// /// Tooltip은 UI 요소에 마우스를 올렸을 때 나타나는 작은 설명 텍스트입니다. /// 버튼이나 아이콘의 기능을 설명하거나 추가 정보를 제공할 때 사용합니다. /// 일반적으로 잠시 후(500ms) 나타나고, 마우스가 벗어나면 사라집니다. /// /// /// 싱글톤 패턴: /// /// UTKTooltipManager는 싱글톤으로 구현되어 있습니다. /// UTKTooltipManager.Instance로 접근하며, 앱 전체에서 하나의 툴팁 UI를 공유합니다. /// 사용 전에 반드시 Initialize(root)를 호출해야 합니다. /// /// /// 주요 기능: /// /// 지연 표시 - 마우스 오버 후 일정 시간 뒤에 표시 /// 마우스 따라가기 - 마우스 이동에 따라 위치 업데이트 /// 화면 경계 처리 - 화면 밖으로 나가지 않도록 자동 조정 /// 다국어 지원 - 로컬라이제이션 키 자동 변환 /// /// /// 주요 메서드: /// /// Initialize(root) - 초기화 (루트 요소 지정) /// AttachTooltip(element, text) - 요소에 툴팁 연결 /// DetachTooltip(element) - 툴팁 제거 /// Show(text, position) - 즉시 표시 /// Hide() - 숨기기 /// /// /// 실제 활용 예시: /// /// 아이콘 버튼 - "저장", "삭제", "설정" 등 기능 설명 /// 복잡한 옵션 - 설정 항목의 상세 설명 /// 잘린 텍스트 - 전체 내용 표시 /// 단축키 안내 - "Ctrl+S" 등 키보드 힌트 /// /// /// /// C# 코드에서 사용: /// /// // 1. 초기화 (앱 시작 시 한 번) /// UTKTooltipManager.Instance.Initialize(rootVisualElement); /// /// // 2. 버튼에 툴팁 연결 /// var saveButton = new UTKButton("", UTKMaterialIcons.Save); /// UTKTooltipManager.Instance.AttachTooltip(saveButton, "저장 (Ctrl+S)"); /// /// // 3. 다국어 키로 툴팁 연결 /// UTKTooltipManager.Instance.AttachTooltip(settingsButton, "tooltip_settings"); /// /// // 4. 툴팁 업데이트 /// UTKTooltipManager.Instance.UpdateTooltip(button, "새로운 설명"); /// /// // 5. 툴팁 제거 /// UTKTooltipManager.Instance.DetachTooltip(button); /// /// public class UTKTooltipManager : IDisposable { #region Singleton private static UTKTooltipManager? _instance; public static UTKTooltipManager Instance => _instance ??= new UTKTooltipManager(); protected UTKTooltipManager() { } #endregion #region Constants private const string UXML_PATH = "UIToolkit/Common/UTKTooltip"; private const string USS_PATH = "UIToolkit/Common/UTKTooltip"; private const int SHOW_DELAY_MS = 500; private const int POSITION_OFFSET = 10; #endregion #region Fields private VisualElement? _root; private VisualElement? _tooltipContainer; private Label? _tooltipLabel; private bool _isInitialized; private bool _isVisible; private bool _disposed; private CancellationTokenSource? _showDelayCts; private readonly Dictionary _tooltipRegistry = new(); private readonly Dictionary> _enterCallbacks = new(); private readonly Dictionary> _leaveCallbacks = new(); private readonly Dictionary> _moveCallbacks = new(); #endregion #region Properties public bool IsInitialized => _isInitialized; public bool IsVisible => _isVisible; #endregion #region Initialization /// /// 툴팁 매니저를 초기화합니다. /// /// VisualElement 트리의 루트 public void Initialize(VisualElement root) { if (_isInitialized) { Debug.LogWarning("[UTKTooltipManager] Already initialized."); return; } _root = root; // UXML 로드 시도 var visualTree = Resources.Load(UXML_PATH); if (visualTree != null) { _tooltipContainer = visualTree.Instantiate(); _tooltipContainer.name = "utk-tooltip-container"; _tooltipLabel = _tooltipContainer.Q