333 lines
10 KiB
C#
333 lines
10 KiB
C#
#nullable enable
|
||
using System;
|
||
using UnityEngine;
|
||
using UnityEngine.UIElements;
|
||
using UVC.UIToolkit.Modal;
|
||
|
||
namespace UVC.UIToolkit
|
||
{
|
||
/// <summary>
|
||
/// Alert 팝업 컴포넌트.
|
||
/// 사용자에게 중요한 정보를 알립니다.
|
||
/// </summary>
|
||
[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
|
||
/// <summary>닫힘 이벤트</summary>
|
||
public event Action? OnClosed;
|
||
/// <summary>확인 이벤트</summary>
|
||
public event Action? OnConfirm;
|
||
/// <summary>취소 이벤트</summary>
|
||
public event Action? OnCancel;
|
||
#endregion
|
||
|
||
#region Properties
|
||
/// <summary>제목</summary>
|
||
[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;
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>메시지</summary>
|
||
[UxmlAttribute]
|
||
public string Message
|
||
{
|
||
get => _message;
|
||
set
|
||
{
|
||
_message = value;
|
||
if (_messageLabel != null) _messageLabel.text = value;
|
||
}
|
||
}
|
||
|
||
/// <summary>알림 유형</summary>
|
||
[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<StyleSheet>(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
|
||
/// <summary>
|
||
/// Info 알림 표시
|
||
/// </summary>
|
||
public static UTKAlert ShowInfo(VisualElement parent, string title, string message, Action? onClose = null)
|
||
{
|
||
return Show(parent, title, message, AlertType.Info, onClose);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Success 알림 표시
|
||
/// </summary>
|
||
public static UTKAlert ShowSuccess(VisualElement parent, string title, string message, Action? onClose = null)
|
||
{
|
||
return Show(parent, title, message, AlertType.Success, onClose);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Warning 알림 표시
|
||
/// </summary>
|
||
public static UTKAlert ShowWarning(VisualElement parent, string title, string message, Action? onClose = null)
|
||
{
|
||
return Show(parent, title, message, AlertType.Warning, onClose);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Error 알림 표시
|
||
/// </summary>
|
||
public static UTKAlert ShowError(VisualElement parent, string title, string message, Action? onClose = null)
|
||
{
|
||
return Show(parent, title, message, AlertType.Error, onClose);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Confirm 대화상자 표시
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 알림 표시
|
||
/// </summary>
|
||
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<DetachFromPanelEvent>(_ =>
|
||
{
|
||
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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 알림 닫기
|
||
/// </summary>
|
||
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
|
||
}
|
||
}
|