Files
EnglewoodLAB/Assets/Scripts/Studio/UIToolkit/Dropdown/UTKLanguageDropdownController.cs

153 lines
5.1 KiB
C#

#nullable enable
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UVC.Locale;
using UVC.UIToolkit;
namespace UVC.Studio.UIToolkit
{
/// <summary>
/// 언어 선택 드롭다운 컴포넌트.
/// 내부적으로 <see cref="UTKButtonDropdown"/>을 사용하며,
/// <see cref="LocalizationManager"/>에서 지원 언어 목록을 가져와 표시합니다.
/// 선택 시 <see cref="LocalizationManager.SetCurrentLanguage"/>를 호출하고,
/// 외부에서 언어가 변경되면 <see cref="LocalizationManager.OnLanguageChanged"/> 이벤트를 통해 자동 동기화됩니다.
/// </summary>
/// <example>
/// <para><b>C# 코드에서 사용:</b></para>
/// <code>
/// var dropdown = new UTKLanguageDropdownController();
/// container.Add(dropdown);
///
/// // 씬 초기화 완료 후 언어 목록 로드
/// dropdown.LoadLanguages();
/// </code>
/// <para><b>UXML에서 사용:</b></para>
/// <code>
/// <ui:UXML xmlns:studio="UVC.Studio.UIToolkit">
/// <studio:UTKLanguageDropdownController />
/// </ui:UXML>
/// </code>
/// </example>
[UxmlElement]
public partial class UTKLanguageDropdownController : VisualElement, IDisposable
{
#region Fields
private bool _disposed;
// 언어 코드 목록 (인덱스 매핑용): ["ko", "en", ...]
private List<string> _languageCodes = new();
// 내부 드롭다운 컴포넌트
private readonly UTKButtonDropdown _dropdown;
#endregion
#region Properties
/// <summary>활성화 상태.</summary>
[UxmlAttribute("is-enabled")]
public bool IsEnabled
{
get => _dropdown.IsEnabled;
set => _dropdown.IsEnabled = value;
}
/// <summary>현재 선택된 언어 코드 (읽기 전용).</summary>
public string? SelectedLanguageCode
{
get
{
int idx = _dropdown.SelectedIndex;
return idx >= 0 && idx < _languageCodes.Count ? _languageCodes[idx] : null;
}
}
#endregion
#region Constructor
public UTKLanguageDropdownController()
{
_dropdown = new UTKButtonDropdown();
if(_dropdown.TriggerButton != null) {
_dropdown.TriggerButton.SetMaterialIcon(UTKMaterialIcons.Language, 18);
_dropdown.TriggerButton.Text = "KOR";
}
Add(_dropdown);
_dropdown.OnSelectionChanged += OnDropdownSelectionChanged;
LocalizationManager.Instance.OnReady += LoadLanguages;
}
#endregion
#region Public Methods
/// <summary>
/// <see cref="LocalizationManager"/>에서 지원 언어 목록을 읽어 드롭다운을 초기화합니다.
/// 씬 초기화(Initialized 이벤트) 완료 후 호출해야 합니다.
/// </summary>
private void LoadLanguages()
{
var displayLanguages = LocalizationManager.Instance.AvailableDisplayLanguages;
_languageCodes.Clear();
var displayNames = new List<string>();
foreach (var kv in displayLanguages)
{
_languageCodes.Add(kv.Key);
displayNames.Add(kv.Value);
}
_dropdown.SetOptions(displayNames);
// 현재 언어로 초기 선택 동기화 (이벤트 없이)
SyncToCurrentLanguage();
// 외부 언어 변경 감지
LocalizationManager.Instance.OnLanguageChanged -= OnLanguageChanged;
LocalizationManager.Instance.OnLanguageChanged += OnLanguageChanged;
}
#endregion
#region Event Handlers
private void OnDropdownSelectionChanged(int index, string displayName)
{
if (index < 0 || index >= _languageCodes.Count) return;
LocalizationManager.Instance.SetCurrentLanguage(_languageCodes[index]);
}
private void OnLanguageChanged(string newLanguageCode)
{
// 외부에서 언어 변경 시 드롭다운 선택 동기화
SyncToCurrentLanguage();
}
#endregion
#region Private Methods
private void SyncToCurrentLanguage()
{
string currentCode = LocalizationManager.Instance.CurrentLanguage;
int index = _languageCodes.IndexOf(currentCode);
if (index >= 0)
{
// notify: false — SetCurrentLanguage 재호출 방지
_dropdown.SetSelectedIndex(index, notify: false);
}
}
#endregion
#region IDisposable
/// <summary>이벤트 구독 및 내부 드롭다운을 해제합니다.</summary>
public void Dispose()
{
if (_disposed) return;
_disposed = true;
LocalizationManager.Instance.OnLanguageChanged -= OnLanguageChanged;
_dropdown.OnSelectionChanged -= OnDropdownSelectionChanged;
_dropdown.Dispose();
}
#endregion
}
}