#nullable enable
using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace UVC.UIToolkit
{
///
/// 프로그레스 바 컴포넌트.
/// Unity ProgressBar를 래핑하여 커스텀 스타일을 적용합니다.
///
///
/// C# 코드에서 사용:
///
/// // 기본 프로그레스 바
/// var progressBar = new UTKProgressBar();
/// progressBar.title = "다운로드 중...";
/// progressBar.MinValue = 0;
/// progressBar.MaxValue = 100;
/// progressBar.Value = 50;
///
/// // 값 표시 설정
/// progressBar.ShowValue = true;
/// progressBar.ShowPercentage = true;
///
/// // 무한 로딩 (불확정 상태)
/// progressBar.IsIndeterminate = true;
///
/// // 변형 스타일
/// progressBar.Variant = UTKProgressBar.ProgressBarVariant.Success;
///
/// UXML에서 사용:
///
///
///
///
///
///
///
///
///
///
///
///
///
[UxmlElement]
public partial class UTKProgressBar : ProgressBar, IDisposable
{
#region Constants
private const string USS_PATH = "UIToolkit/Slider/UTKProgressBar";
#endregion
#region Fields
private bool _disposed;
private bool _showValue = true;
private bool _showPercentage = true;
private bool _isIndeterminate;
private ProgressBarVariant _variant = ProgressBarVariant.Default;
#endregion
#region Properties
/// 현재 값
public float Value
{
get => value;
set => SetValue(value);
}
/// 최소값
public float MinValue
{
get => lowValue;
set
{
lowValue = value;
UpdateValueLabel();
}
}
/// 최대값
public float MaxValue
{
get => highValue;
set
{
highValue = value;
UpdateValueLabel();
}
}
/// 값 표시 여부
[UxmlAttribute("show-value")]
public bool ShowValue
{
get => _showValue;
set
{
_showValue = value;
UpdateValueLabel();
}
}
/// 퍼센트로 표시 여부
[UxmlAttribute("show-percentage")]
public bool ShowPercentage
{
get => _showPercentage;
set
{
_showPercentage = value;
UpdateValueLabel();
}
}
/// 불확정 상태 (애니메이션)
[UxmlAttribute("is-indeterminate")]
public bool IsIndeterminate
{
get => _isIndeterminate;
set
{
_isIndeterminate = value;
EnableInClassList("utk-progress--indeterminate", value);
UpdateValueLabel();
}
}
/// 스타일 변형
[UxmlAttribute("variant")]
public ProgressBarVariant Variant
{
get => _variant;
set
{
_variant = value;
UpdateVariant();
}
}
#endregion
#region Enums
public enum ProgressBarVariant
{
Default,
Success,
Warning,
Error
}
#endregion
#region Constructor
public UTKProgressBar() : base()
{
UTKThemeManager.Instance.ApplyThemeToElement(this);
var uss = Resources.Load(USS_PATH);
if (uss != null)
{
styleSheets.Add(uss);
}
SetupStyles();
SubscribeToThemeChanges();
}
public UTKProgressBar(string text, float value = 0f, float maxValue = 100f) : this()
{
title = text;
highValue = maxValue;
SetValue(value);
}
#endregion
#region Setup
private void SetupStyles()
{
AddToClassList("utk-progress");
UpdateVariant();
UpdateValueLabel();
}
private void SubscribeToThemeChanges()
{
UTKThemeManager.Instance.OnThemeChanged += OnThemeChanged;
RegisterCallback(_ =>
{
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
});
}
private void OnThemeChanged(UTKTheme theme)
{
UTKThemeManager.Instance.ApplyThemeToElement(this);
}
#endregion
#region Methods
///
/// 값 설정
///
public void SetValue(float newValue)
{
value = Mathf.Clamp(newValue, lowValue, highValue);
UpdateValueLabel();
}
private void UpdateValueLabel()
{
if (_isIndeterminate || !_showValue)
{
title = title?.Split(' ')[0] ?? "";
return;
}
string baseTitle = title?.Split(' ')[0] ?? "";
if (_showPercentage)
{
float range = highValue - lowValue;
float percent = range > 0 ? (value - lowValue) / range * 100 : 0;
title = string.IsNullOrEmpty(baseTitle) ? $"{percent:F0}%" : $"{baseTitle} {percent:F0}%";
}
else
{
title = string.IsNullOrEmpty(baseTitle) ? $"{value:F0}/{highValue:F0}" : $"{baseTitle} {value:F0}/{highValue:F0}";
}
}
private void UpdateVariant()
{
RemoveFromClassList("utk-progress--default");
RemoveFromClassList("utk-progress--success");
RemoveFromClassList("utk-progress--warning");
RemoveFromClassList("utk-progress--error");
var variantClass = _variant switch
{
ProgressBarVariant.Success => "utk-progress--success",
ProgressBarVariant.Warning => "utk-progress--warning",
ProgressBarVariant.Error => "utk-progress--error",
_ => "utk-progress--default"
};
AddToClassList(variantClass);
}
#endregion
#region IDisposable
public void Dispose()
{
if (_disposed) return;
_disposed = true;
UTKThemeManager.Instance.OnThemeChanged -= OnThemeChanged;
}
#endregion
}
}