2026-01-08 20:15:57 +09:00
|
|
|
#nullable enable
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using UnityEngine.UIElements;
|
|
|
|
|
|
2026-01-20 20:18:47 +09:00
|
|
|
namespace UVC.UIToolkit
|
2026-01-08 20:15:57 +09:00
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 라디오 그룹 속성 아이템
|
2026-02-02 19:33:27 +09:00
|
|
|
/// UTKRadioButton 그룹으로 단일 선택
|
2026-01-08 20:15:57 +09:00
|
|
|
/// </summary>
|
|
|
|
|
public class UTKRadioPropertyItem : UTKPropertyItemBase<int>
|
|
|
|
|
{
|
|
|
|
|
#region Fields
|
2026-02-02 19:33:27 +09:00
|
|
|
private VisualElement? _radioContainer;
|
|
|
|
|
private List<UTKRadioButton> _radioButtons = new();
|
2026-01-08 20:15:57 +09:00
|
|
|
private List<string> _choices;
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Properties
|
|
|
|
|
public override UTKPropertyType PropertyType => UTKPropertyType.RadioGroup;
|
|
|
|
|
|
|
|
|
|
/// <summary>선택 가능한 항목 목록</summary>
|
|
|
|
|
public List<string> Choices
|
|
|
|
|
{
|
|
|
|
|
get => _choices;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
_choices = value ?? new List<string>();
|
2026-02-02 19:33:27 +09:00
|
|
|
RebuildRadioButtons();
|
2026-01-08 20:15:57 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>현재 선택된 항목의 텍스트</summary>
|
|
|
|
|
public string? SelectedText
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (Value >= 0 && Value < _choices.Count)
|
|
|
|
|
{
|
|
|
|
|
return _choices[Value];
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Constructor
|
2026-02-03 20:43:36 +09:00
|
|
|
public UTKRadioPropertyItem(string id, string name, List<string> choices, int selectedIndex = 0, bool isReadOnly = false)
|
2026-01-08 20:15:57 +09:00
|
|
|
: base(id, name, Math.Max(0, Math.Min(selectedIndex, (choices?.Count ?? 1) - 1)))
|
|
|
|
|
{
|
2026-02-03 20:43:36 +09:00
|
|
|
base._isReadOnly = isReadOnly;
|
2026-01-08 20:15:57 +09:00
|
|
|
_choices = choices ?? new List<string>();
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-03 20:43:36 +09:00
|
|
|
public UTKRadioPropertyItem(string id, string name, IEnumerable<string> choices, int selectedIndex = 0, bool isReadOnly = false)
|
|
|
|
|
: this(id, name, choices?.ToList() ?? new List<string>(), selectedIndex, isReadOnly)
|
2026-01-08 20:15:57 +09:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Override Methods
|
|
|
|
|
public override VisualElement CreateUI()
|
2026-02-02 19:33:27 +09:00
|
|
|
{
|
|
|
|
|
var container = CreateUIFromUxml("UTKRadioPropertyItem");
|
|
|
|
|
if (container == null)
|
|
|
|
|
{
|
|
|
|
|
return CreateUIFallback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_radioContainer = container.Q<VisualElement>("radio-container");
|
|
|
|
|
if (_radioContainer != null)
|
|
|
|
|
{
|
|
|
|
|
CreateRadioButtons();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return container;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private VisualElement CreateUIFallback()
|
2026-01-08 20:15:57 +09:00
|
|
|
{
|
|
|
|
|
var container = CreateContainer();
|
|
|
|
|
|
|
|
|
|
var label = CreateNameLabel();
|
|
|
|
|
container.Add(label);
|
|
|
|
|
|
|
|
|
|
var valueContainer = new VisualElement();
|
|
|
|
|
valueContainer.AddToClassList("utk-property-item__value");
|
|
|
|
|
|
2026-02-02 19:33:27 +09:00
|
|
|
_radioContainer = new VisualElement();
|
|
|
|
|
_radioContainer.name = "radio-container";
|
|
|
|
|
_radioContainer.AddToClassList("utk-property-item__radio-container");
|
|
|
|
|
valueContainer.Add(_radioContainer);
|
|
|
|
|
|
|
|
|
|
CreateRadioButtons();
|
2026-01-08 20:15:57 +09:00
|
|
|
|
|
|
|
|
container.Add(valueContainer);
|
|
|
|
|
|
|
|
|
|
return container;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void BindUI(VisualElement element)
|
|
|
|
|
{
|
|
|
|
|
base.BindUI(element);
|
|
|
|
|
|
2026-02-02 19:33:27 +09:00
|
|
|
_radioContainer = element.Q<VisualElement>("radio-container");
|
2026-01-08 20:15:57 +09:00
|
|
|
|
2026-02-02 19:33:27 +09:00
|
|
|
if (_radioContainer != null)
|
2026-01-08 20:15:57 +09:00
|
|
|
{
|
2026-02-02 19:33:27 +09:00
|
|
|
// 기존 라디오 버튼 찾기 또는 새로 생성
|
|
|
|
|
_radioButtons.Clear();
|
|
|
|
|
var existingButtons = _radioContainer.Query<UTKRadioButton>().ToList();
|
|
|
|
|
|
|
|
|
|
if (existingButtons.Count == _choices.Count)
|
|
|
|
|
{
|
|
|
|
|
// 기존 버튼 재사용
|
|
|
|
|
for (int i = 0; i < existingButtons.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var radio = existingButtons[i];
|
|
|
|
|
_radioButtons.Add(radio);
|
|
|
|
|
radio.IsEnabled = !IsReadOnly;
|
|
|
|
|
|
|
|
|
|
int index = i;
|
|
|
|
|
radio.OnValueChanged += (isChecked) => OnRadioChanged(index, isChecked);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 새로 생성
|
|
|
|
|
CreateRadioButtons();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateSelection();
|
2026-01-08 20:15:57 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void UnbindUI(VisualElement element)
|
|
|
|
|
{
|
2026-02-02 19:33:27 +09:00
|
|
|
_radioButtons.Clear();
|
|
|
|
|
_radioContainer = null;
|
2026-01-08 20:15:57 +09:00
|
|
|
|
|
|
|
|
base.UnbindUI(element);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void RefreshUI()
|
|
|
|
|
{
|
2026-02-02 19:33:27 +09:00
|
|
|
UpdateSelection();
|
2026-01-08 20:15:57 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override void UpdateReadOnlyState()
|
|
|
|
|
{
|
|
|
|
|
base.UpdateReadOnlyState();
|
|
|
|
|
|
2026-02-02 19:33:27 +09:00
|
|
|
foreach (var radio in _radioButtons)
|
2026-01-08 20:15:57 +09:00
|
|
|
{
|
2026-02-02 19:33:27 +09:00
|
|
|
radio.IsEnabled = !IsReadOnly;
|
2026-01-08 20:15:57 +09:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Public Methods
|
|
|
|
|
/// <summary>텍스트로 선택</summary>
|
|
|
|
|
public void SelectByText(string text)
|
|
|
|
|
{
|
|
|
|
|
int index = _choices.IndexOf(text);
|
|
|
|
|
if (index >= 0)
|
|
|
|
|
{
|
|
|
|
|
Value = index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Private Methods
|
2026-02-02 19:33:27 +09:00
|
|
|
private void CreateRadioButtons()
|
2026-01-08 20:15:57 +09:00
|
|
|
{
|
2026-02-02 19:33:27 +09:00
|
|
|
if (_radioContainer == null) return;
|
|
|
|
|
|
|
|
|
|
_radioContainer.Clear();
|
|
|
|
|
_radioButtons.Clear();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < _choices.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var radio = new UTKRadioButton(_choices[i]);
|
|
|
|
|
radio.name = $"radio-{i}";
|
|
|
|
|
radio.AddToClassList("utk-property-item__radio");
|
|
|
|
|
|
|
|
|
|
int index = i;
|
2026-02-03 20:43:36 +09:00
|
|
|
radio.OnValueChanged += (isChecked) => OnRadioChanged(index, isChecked);
|
|
|
|
|
radio.IsEnabled = !IsReadOnly;
|
|
|
|
|
|
2026-02-02 19:33:27 +09:00
|
|
|
_radioButtons.Add(radio);
|
|
|
|
|
_radioContainer.Add(radio);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateSelection();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void RebuildRadioButtons()
|
|
|
|
|
{
|
|
|
|
|
if (_radioContainer != null)
|
|
|
|
|
{
|
|
|
|
|
CreateRadioButtons();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateSelection()
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < _radioButtons.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
_radioButtons[i].SetChecked(i == Value, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnRadioChanged(int index, bool isChecked)
|
|
|
|
|
{
|
|
|
|
|
if (isChecked && index != Value)
|
|
|
|
|
{
|
|
|
|
|
// 다른 라디오 버튼 해제
|
|
|
|
|
for (int i = 0; i < _radioButtons.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (i != index)
|
|
|
|
|
{
|
|
|
|
|
_radioButtons[i].SetChecked(false, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Value = index;
|
|
|
|
|
}
|
2026-01-08 20:15:57 +09:00
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|