#nullable enable using System; using UnityEngine; using UnityEngine.UIElements; namespace UVC.UIToolkit { /// /// 버튼 속성 View 클래스입니다. /// UTKButton을 표시하고 클릭 시 Action 이름을 이벤트로 전달합니다. /// [UxmlElement] public partial class UTKButtonItemView : UTKPropertyItemViewBase, IUTKPropertyItemView { #region Fields private UTKButton? _button; private IUTKPropertyItem? _boundData; #endregion #region Properties protected override string ViewTypeName => "UTKButtonItemView"; /// 값 변경 이벤트 (IUTKPropertyItemView 인터페이스 구현) public event Action? OnValueChanged; /// 버튼 클릭 이벤트 public event Action? OnButtonClicked; /// 액션 이름 (현재 Value) public string Value { get => _boundData?.Value ?? ""; set { if (_boundData != null) { _boundData.Value = value; } } } #endregion #region Constructor public UTKButtonItemView() : base() { InitializeUI(); } public UTKButtonItemView(UTKButtonItem data) : this() { Bind(data); } #endregion #region Initialization private void InitializeUI() { AddToClassList("utk-property-item-view"); AddToClassList("utk-property-item-view--button"); if (!CreateUIFromUxml()) { CreateUIFallback(); } QueryUIElements(); } private void QueryUIElements() { if (_valueContainer == null) return; _button = this.Q("button-field"); if (_button == null) { _button = new UTKButton { name = "button-field" }; _button.AddToClassList("utk-property-item-view__button"); _valueContainer.Add(_button); } // 버튼 클릭 이벤트 등록 _button.OnClicked += OnButtonClickedInternal; } #endregion #region Override Methods protected override void CreateValueUI(VisualElement container) { // Fallback: UXML 로드 실패 시 코드로 생성 _button = new UTKButton { name = "button-field" }; _button.AddToClassList("utk-property-item-view__button"); container.Add(_button); _button.OnClicked += OnButtonClickedInternal; } public override void RefreshUI() { // 버튼은 정적이므로 별도 갱신 불필요 } protected override void OnReadOnlyStateChanged(bool isReadOnly) { // 버튼은 ReadOnly 개념이 적용되지 않으므로 IsEnabled로 제어 if (_button != null) { _button.IsEnabled = !isReadOnly; } } #endregion #region Event Handling private void OnButtonClickedInternal() { if (_boundData is UTKButtonItem buttonItem) { OnButtonClicked?.Invoke(buttonItem.ActionName); } } #endregion #region Data Binding public void Bind(IUTKPropertyItem data) { if (data is IUTKPropertyItem stringData) { Bind(stringData); } else { Debug.LogWarning($"[UTKButtonItemView] Cannot bind to non-string data: {data.GetType().Name}"); } } public void Bind(IUTKPropertyItem data) { Unbind(); _boundData = data; // 라벨 텍스트 설정 if (_labelElement != null) { _labelElement.Text = data.DisplayName; } // UTKButtonItem 설정 적용 if (data is UTKButtonItem buttonItem && _button != null) { _button.Text = buttonItem.Text; _button.Icon = buttonItem.Icon; _button.IconSize = buttonItem.IconSize; _button.Variant = buttonItem.Variant; _button.Size = buttonItem.Size; _button.IconOnly = buttonItem.IconOnly; if (buttonItem.BackgroundColor.HasValue) { _button.BackgroundColor = buttonItem.BackgroundColor; } if (buttonItem.BorderWidth >= 0) { _button.BorderWidth = buttonItem.BorderWidth; } _button.IsEnabled = !buttonItem.IsReadOnly; // 라벨 표시 여부 제어 if (_labelElement != null) { if (buttonItem.ShowLabel) { _labelElement.style.display = DisplayStyle.Flex; RemoveFromClassList("utk-property-item-view--button-no-label"); } else { _labelElement.style.display = DisplayStyle.None; AddToClassList("utk-property-item-view--button-no-label"); } } } IsReadOnly = data.IsReadOnly; IsVisible = data.IsVisible; TooltipText = data.Tooltip; } public void Unbind() { if (_boundData != null) { _boundData = null; } } #endregion #region Dispose protected override void Dispose(bool disposing) { if (_disposed) return; if (disposing) { if (_button != null) { _button.OnClicked -= OnButtonClickedInternal; _button.Dispose(); } Unbind(); OnValueChanged = null; OnButtonClicked = null; _button = null; } base.Dispose(disposing); } #endregion } }