274 lines
7.3 KiB
C#
274 lines
7.3 KiB
C#
#nullable enable
|
|
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
|
|
namespace UVC.UIToolkit
|
|
{
|
|
/// <summary>
|
|
/// Bool 속성 View 클래스입니다.
|
|
/// UTKToggle 또는 UTKLabel (ReadOnly 시)을 사용하여 bool 값을 표시/편집합니다.
|
|
///
|
|
/// <para><b>사용법 (단독 사용):</b></para>
|
|
/// <code>
|
|
/// // C# 코드에서 생성
|
|
/// var view = new UTKBoolPropertyItemView();
|
|
/// view.Label = "활성화";
|
|
/// view.Value = true;
|
|
/// parent.Add(view);
|
|
///
|
|
/// // UXML에서 사용
|
|
/// <utk:UTKBoolPropertyItemView label="활성화" value="true" />
|
|
/// </code>
|
|
/// </summary>
|
|
[UxmlElement]
|
|
public partial class UTKBoolPropertyItemView : UTKPropertyItemViewBase, IUTKPropertyItemView<bool>
|
|
{
|
|
#region Fields
|
|
private UTKToggle? _toggle;
|
|
private UTKLabel? _stateLabel;
|
|
|
|
private bool _value;
|
|
private IUTKPropertyItem<bool>? _boundData;
|
|
#endregion
|
|
|
|
#region Properties
|
|
protected override string ViewTypeName => "UTKBoolPropertyItemView";
|
|
|
|
/// <summary>현재 값</summary>
|
|
[UxmlAttribute("value")]
|
|
public bool Value
|
|
{
|
|
get => _value;
|
|
set
|
|
{
|
|
if (_value != value)
|
|
{
|
|
_value = value;
|
|
UpdateValueUI();
|
|
OnValueChanged?.Invoke(value);
|
|
|
|
if (_boundData != null && _boundData.Value != value)
|
|
{
|
|
_boundData.Value = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Events
|
|
public event Action<bool>? OnValueChanged;
|
|
#endregion
|
|
|
|
#region Constructor
|
|
public UTKBoolPropertyItemView() : base()
|
|
{
|
|
InitializeUI();
|
|
}
|
|
|
|
public UTKBoolPropertyItemView(string label, bool value = false) : base()
|
|
{
|
|
_value = value;
|
|
Label = label;
|
|
InitializeUI();
|
|
}
|
|
#endregion
|
|
|
|
#region Initialization
|
|
private void InitializeUI()
|
|
{
|
|
AddToClassList("utk-property-item-view");
|
|
AddToClassList("utk-property-item-view--bool");
|
|
|
|
if (!CreateUIFromUxml())
|
|
{
|
|
CreateUIFallback();
|
|
}
|
|
|
|
// UXML에서 요소 가져오기
|
|
QueryUIElements();
|
|
|
|
// 이벤트 등록
|
|
RegisterEvents();
|
|
|
|
UpdateValueUI();
|
|
UpdateReadOnlyState();
|
|
}
|
|
|
|
private void QueryUIElements()
|
|
{
|
|
_toggle = this.Q<UTKToggle>("value-field");
|
|
_stateLabel = this.Q<UTKLabel>("state-label");
|
|
|
|
// Fallback: UXML에서 못 찾으면 생성
|
|
if (_valueContainer != null)
|
|
{
|
|
if (_toggle == null)
|
|
{
|
|
_toggle = new UTKToggle
|
|
{
|
|
name = "value-field",
|
|
IsOn = _value,
|
|
IsInteractive = true
|
|
};
|
|
_toggle.AddToClassList("utk-property-item-view__toggle");
|
|
_valueContainer.Add(_toggle);
|
|
}
|
|
|
|
if (_stateLabel == null)
|
|
{
|
|
_stateLabel = new UTKLabel(_value ? "True" : "False", UTKLabel.LabelSize.Body2)
|
|
{
|
|
name = "state-label"
|
|
};
|
|
_stateLabel.AddToClassList("utk-property-item-view__state-label");
|
|
_valueContainer.Add(_stateLabel);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void RegisterEvents()
|
|
{
|
|
if (_toggle != null)
|
|
{
|
|
_toggle.OnValueChanged += OnToggleChanged;
|
|
}
|
|
}
|
|
|
|
private void UnregisterEvents()
|
|
{
|
|
if (_toggle != null)
|
|
{
|
|
_toggle.OnValueChanged -= OnToggleChanged;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Override Methods
|
|
protected override void CreateValueUI(VisualElement container)
|
|
{
|
|
// UXML/USS 기반으로 display 조절하므로 여기서는 생성하지 않음
|
|
}
|
|
|
|
public override void RefreshUI()
|
|
{
|
|
UpdateValueUI();
|
|
}
|
|
|
|
protected override void OnReadOnlyStateChanged(bool isReadOnly)
|
|
{
|
|
// USS에서 .utk-property-item-view--readonly 클래스로 display 조절
|
|
// Toggle의 상호작용 상태도 업데이트
|
|
if (_toggle != null)
|
|
{
|
|
_toggle.IsInteractive = !isReadOnly;
|
|
}
|
|
UpdateValueUI();
|
|
}
|
|
#endregion
|
|
|
|
#region Event Handling
|
|
private void OnToggleChanged(bool newValue)
|
|
{
|
|
if (_value != newValue)
|
|
{
|
|
_value = newValue;
|
|
OnValueChanged?.Invoke(newValue);
|
|
|
|
if (_boundData != null && _boundData.Value != newValue)
|
|
{
|
|
_boundData.Value = newValue;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Value Update
|
|
private void UpdateValueUI()
|
|
{
|
|
if (_toggle != null && _toggle.IsOn != _value)
|
|
{
|
|
_toggle.SetOn(_value, false);
|
|
}
|
|
|
|
if (_stateLabel != null)
|
|
{
|
|
_stateLabel.Text = _value ? "True" : "False";
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Data Binding
|
|
public void Bind(IUTKPropertyItem data)
|
|
{
|
|
if (data is IUTKPropertyItem<bool> boolData)
|
|
{
|
|
Bind(boolData);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"[UTKBoolPropertyItemView] Cannot bind to non-bool data: {data.GetType().Name}");
|
|
}
|
|
}
|
|
|
|
public void Bind(IUTKPropertyItem<bool> data)
|
|
{
|
|
Unbind();
|
|
|
|
_boundData = data;
|
|
BindBase(data);
|
|
|
|
Label = data.Name;
|
|
_value = data.Value;
|
|
IsVisible = data.IsVisible;
|
|
TooltipText = data.Tooltip;
|
|
ShowLabel = data.ShowLabel;
|
|
|
|
data.OnTypedValueChanged += OnDataValueChanged;
|
|
|
|
UpdateValueUI();
|
|
IsReadOnly = data.IsReadOnly;
|
|
}
|
|
|
|
public void Unbind()
|
|
{
|
|
if (_boundData != null)
|
|
{
|
|
_boundData.OnTypedValueChanged -= OnDataValueChanged;
|
|
UnbindBase();
|
|
_boundData = null;
|
|
}
|
|
}
|
|
|
|
private void OnDataValueChanged(IUTKPropertyItem<bool> item, bool oldValue, bool newValue)
|
|
{
|
|
if (_value != newValue)
|
|
{
|
|
_value = newValue;
|
|
UpdateValueUI();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Dispose
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (_disposed) return;
|
|
|
|
if (disposing)
|
|
{
|
|
UnregisterEvents();
|
|
Unbind();
|
|
|
|
OnValueChanged = null;
|
|
_toggle = null;
|
|
_stateLabel = null;
|
|
}
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
#endregion
|
|
}
|
|
}
|