#nullable enable using System; using UnityEngine; using UnityEngine.UIElements; using UVC.UIToolkit.Modal; namespace UVC.UIToolkit { /// /// Alert 팝업 컴포넌트. /// 사용자에게 중요한 정보를 알립니다. /// [UxmlElement] public partial class UTKAlert : VisualElement, IDisposable { #region Constants private const string USS_PATH = "UIToolkit/Modal/UTKAlert"; #endregion #region Fields private bool _disposed; private UTKModalBlocker? _blocker; private VisualElement? _iconContainer; private Label? _iconLabel; private Label? _titleLabel; private Label? _messageLabel; private VisualElement? _buttonContainer; private string _title = ""; private string _message = ""; private AlertType _alertType = AlertType.Info; #endregion #region Events /// 닫힘 이벤트 public event Action? OnClosed; /// 확인 이벤트 public event Action? OnConfirm; /// 취소 이벤트 public event Action? OnCancel; #endregion #region Properties /// 제목 [UxmlAttribute] public string Title { get => _title; set { _title = value; if (_titleLabel != null) { _titleLabel.text = value; _titleLabel.style.display = string.IsNullOrEmpty(value) ? DisplayStyle.None : DisplayStyle.Flex; } } } /// 메시지 [UxmlAttribute] public string Message { get => _message; set { _message = value; if (_messageLabel != null) _messageLabel.text = value; } } /// 알림 유형 [UxmlAttribute] public AlertType Type { get => _alertType; set { _alertType = value; UpdateType(); } } #endregion #region Enums public enum AlertType { Info, Success, Warning, Error, Confirm } #endregion #region Constructor public UTKAlert() { UTKThemeManager.Instance.ApplyThemeToElement(this); var uss = Resources.Load(USS_PATH); if (uss != null) { styleSheets.Add(uss); } CreateUI(); SubscribeToThemeChanges(); } public UTKAlert(string title, string message, AlertType type = AlertType.Info) : this() { Title = title; Message = message; Type = type; } #endregion #region Static Factory /// /// Info 알림 표시 /// public static UTKAlert ShowInfo(VisualElement parent, string title, string message, Action? onClose = null) { return Show(parent, title, message, AlertType.Info, onClose); } /// /// Success 알림 표시 /// public static UTKAlert ShowSuccess(VisualElement parent, string title, string message, Action? onClose = null) { return Show(parent, title, message, AlertType.Success, onClose); } /// /// Warning 알림 표시 /// public static UTKAlert ShowWarning(VisualElement parent, string title, string message, Action? onClose = null) { return Show(parent, title, message, AlertType.Warning, onClose); } /// /// Error 알림 표시 /// public static UTKAlert ShowError(VisualElement parent, string title, string message, Action? onClose = null) { return Show(parent, title, message, AlertType.Error, onClose); } /// /// Confirm 대화상자 표시 /// public static UTKAlert ShowConfirm(VisualElement parent, string title, string message, Action? onConfirm, Action? onCancel = null) { var alert = Show(parent, title, message, AlertType.Confirm, null); alert.OnConfirm = onConfirm; alert.OnCancel = onCancel; return alert; } /// /// 알림 표시 /// public static UTKAlert Show(VisualElement parent, string title, string message, AlertType type, Action? onClose) { var alert = new UTKAlert(title, message, type); alert.OnClosed = onClose; alert._blocker = UTKModalBlocker.Show(parent, 0.5f, true); alert._blocker.OnBlockerClicked += alert.Close; alert._blocker.Add(alert); // 중앙 정렬 alert.style.position = Position.Absolute; alert.style.left = Length.Percent(50); alert.style.top = Length.Percent(50); alert.style.translate = new Translate(Length.Percent(-50), Length.Percent(-50)); return alert; } #endregion #region UI Creation private void CreateUI() { AddToClassList("utk-alert"); _iconContainer = new VisualElement { name = "icon-container" }; _iconContainer.AddToClassList("utk-alert__icon-container"); Add(_iconContainer); _iconLabel = new Label { name = "icon" }; _iconLabel.AddToClassList("utk-alert__icon"); _iconContainer.Add(_iconLabel); var contentContainer = new VisualElement { name = "content" }; contentContainer.AddToClassList("utk-alert__content"); Add(contentContainer); _titleLabel = new Label { name = "title" }; _titleLabel.AddToClassList("utk-alert__title"); contentContainer.Add(_titleLabel); _messageLabel = new Label { name = "message" }; _messageLabel.AddToClassList("utk-alert__message"); contentContainer.Add(_messageLabel); _buttonContainer = new VisualElement { name = "buttons" }; _buttonContainer.AddToClassList("utk-alert__buttons"); Add(_buttonContainer); UpdateType(); } private void SubscribeToThemeChanges() { UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged; RegisterCallback(_ => { UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; }); } private void OnThemeChanged(UTKTheme theme) { UTKThemeManager.Instance.ApplyThemeToElement(this); } #endregion #region Methods private void UpdateType() { RemoveFromClassList("utk-alert--info"); RemoveFromClassList("utk-alert--success"); RemoveFromClassList("utk-alert--warning"); RemoveFromClassList("utk-alert--error"); RemoveFromClassList("utk-alert--confirm"); var typeClass = _alertType switch { AlertType.Success => "utk-alert--success", AlertType.Warning => "utk-alert--warning", AlertType.Error => "utk-alert--error", AlertType.Confirm => "utk-alert--confirm", _ => "utk-alert--info" }; AddToClassList(typeClass); // 아이콘 업데이트 if (_iconLabel != null) { _iconLabel.text = _alertType switch { AlertType.Success => "✓", AlertType.Warning => "⚠", AlertType.Error => "✕", AlertType.Confirm => "?", _ => "ℹ" }; } // 버튼 업데이트 UpdateButtons(); } private void UpdateButtons() { if (_buttonContainer == null) return; _buttonContainer.Clear(); if (_alertType == AlertType.Confirm) { var cancelBtn = new UTKButton("Cancel", "", UTKButton.ButtonVariant.Normal); cancelBtn.AddToClassList("utk-alert__btn"); cancelBtn.OnClicked += () => { OnCancel?.Invoke(); Close(); }; _buttonContainer.Add(cancelBtn); var confirmBtn = new UTKButton("OK", "", UTKButton.ButtonVariant.Primary); confirmBtn.AddToClassList("utk-alert__btn"); confirmBtn.OnClicked += () => { OnConfirm?.Invoke(); Close(); }; _buttonContainer.Add(confirmBtn); } else { var okBtn = new UTKButton("OK", "", UTKButton.ButtonVariant.Primary); okBtn.AddToClassList("utk-alert__btn"); okBtn.OnClicked += Close; _buttonContainer.Add(okBtn); } } /// /// 알림 닫기 /// public void Close() { OnClosed?.Invoke(); if (_blocker != null) { _blocker.OnBlockerClicked -= Close; _blocker.Hide(); } _blocker = null; } #endregion #region IDisposable public void Dispose() { if (_disposed) return; _disposed = true; UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged; OnClosed = null; OnConfirm = null; OnCancel = null; _blocker = null; } #endregion } }