Files
XRLib/Assets/Scripts/UVC/UI/ToolBar/Model/ToolbarRadioButtonGroup.cs
2025-06-18 00:16:49 +09:00

152 lines
7.9 KiB
C#

using System.Collections.Generic;
using System.Linq;
namespace UVC.UI.Toolbar.Model
{
/// <summary>
/// 여러 개의 ToolbarRadioButton 객체들을 하나의 그룹으로 관리합니다.
/// 이 그룹 내에서는 오직 하나의 라디오 버튼만이 선택된(IsSelected = true) 상태를 가질 수 있도록 보장합니다.
/// </summary>
/// <remarks>
/// ToolbarModel은 ToolbarRadioButton이 추가될 때 GroupName을 기준으로 이 클래스의 인스턴스를 생성하거나
/// 기존 인스턴스를 찾아 라디오 버튼을 등록(RegisterButton)합니다.
/// 사용자가 라디오 버튼을 클릭하면, 해당 버튼은 이 그룹의 SetSelected 메서드를 호출하여
/// 자신을 선택 상태로 만들고 그룹 내 다른 버튼들은 선택 해제 상태로 변경합니다.
/// </remarks>
/// <example>
/// <code>
/// // 이 클래스는 주로 ToolbarModel 내부에서 사용됩니다. 개발자가 직접 생성하기보다는
/// // ToolbarModel에 ToolbarRadioButton을 추가함으로써 간접적으로 사용됩니다.
///
/// // ToolbarModel 내부에서의 사용 흐름 (간략화된 예시)
/// // public class ToolbarModel
/// // {
/// // private Dictionary<string, ToolbarRadioButtonGroup> _radioGroups = new Dictionary<string, ToolbarRadioButtonGroup>();
/// //
/// // public void AddItem(IToolbarItem item)
/// // {
/// // if (item is ToolbarRadioButton radioButton)
/// // {
/// // if (!_radioGroups.TryGetValue(radioButton.GroupName, out var group))
/// // {
/// // group = new ToolbarRadioButtonGroup();
/// // _radioGroups.Add(radioButton.GroupName, group);
/// // }
/// // group.RegisterButton(radioButton); // 라디오 버튼을 그룹에 등록
/// // radioButton.RadioGroup = group; // 버튼에 그룹 참조 설정
/// // }
/// // // ...
/// // }
/// // }
///
/// // 그룹 내 버튼 선택 로직 (ToolbarRadioButton의 ExecuteClick 내부에서 호출됨)
/// // ToolbarRadioButtonGroup cameraGroup = new ToolbarRadioButtonGroup();
/// // ToolbarRadioButton radio1 = new ToolbarRadioButton("camera") { Text = "Cam1" };
/// // ToolbarRadioButton radio2 = new ToolbarRadioButton("camera") { Text = "Cam2" };
/// //
/// // cameraGroup.RegisterButton(radio1);
/// // cameraGroup.RegisterButton(radio2);
/// // radio1.RadioGroup = cameraGroup;
/// // radio2.RadioGroup = cameraGroup;
/// //
/// // // radio1을 선택 (radio1.IsSelected = true, radio2.IsSelected = false가 됨)
/// // cameraGroup.SetSelected(radio1);
/// // UnityEngine.Debug.Log($"Radio1 Selected: {radio1.IsSelected}, Radio2 Selected: {radio2.IsSelected}");
/// //
/// // // radio2를 선택 (radio1.IsSelected = false, radio2.IsSelected = true가 됨)
/// // cameraGroup.SetSelected(radio2);
/// // UnityEngine.Debug.Log($"Radio1 Selected: {radio1.IsSelected}, Radio2 Selected: {radio2.IsSelected}");
/// </code>
/// </example>
public class ToolbarRadioButtonGroup
{
private List<ToolbarRadioButton> _buttons = new List<ToolbarRadioButton>();
/// <summary>
/// 현재 그룹 내에서 선택된 라디오 버튼입니다.
/// 선택된 버튼이 없으면 null을 반환할 수 있습니다 (일반적으로 그룹은 항상 하나가 선택되도록 설계되지만, 초기 상태 등 예외 가능).
/// </summary>
public ToolbarRadioButton SelectedButton { get; private set; }
/// <summary>
/// 지정된 라디오 버튼을 이 그룹에 등록합니다.
/// 등록된 버튼은 그룹의 선택 관리 대상이 됩니다.
/// 버튼의 RadioGroup 속성에도 이 그룹의 참조가 설정되어야 합니다 (보통 ToolbarModel에서 처리).
/// </summary>
/// <param name="button">그룹에 등록할 ToolbarRadioButton입니다.</param>
public void RegisterButton(ToolbarRadioButton button)
{
if (!_buttons.Contains(button))
{
_buttons.Add(button);
}
}
/// <summary>
/// 지정된 라디오 버튼을 그룹 내에서 선택된 상태로 설정합니다.
/// 이전에 선택되었던 다른 버튼은 선택 해제 상태(IsSelected = false)로 변경됩니다.
/// </summary>
/// <param name="buttonToSelect">선택할 ToolbarRadioButton입니다. 이 버튼은 반드시 그룹에 미리 등록되어 있어야 합니다.</param>
public void SetSelected(ToolbarRadioButton buttonToSelect)
{
if (buttonToSelect == null || !_buttons.Contains(buttonToSelect))
{
// 그룹에 등록되지 않은 버튼을 선택하려고 하면 무시하거나 경고를 로깅할 수 있습니다.
UnityEngine.Debug.LogWarning($"SetSelected: 버튼 '{buttonToSelect?.Text}' (그룹: {buttonToSelect?.GroupName})은 현재 라디오 그룹에 등록되어 있지 않습니다.");
return;
}
// 이미 선택된 버튼을 다시 클릭한 경우, 상태를 변경하지 않고 유지합니다.
// (라디오 버튼은 일반적으로 한 번 선택되면 사용자가 직접 해제할 수 없고, 다른 버튼을 선택해야 해제됨)
if (SelectedButton == buttonToSelect && buttonToSelect.IsSelected)
{
return;
}
SelectedButton = buttonToSelect; // 새 버튼을 선택된 버튼으로 설정
foreach (var buttonInGroup in _buttons)
{
// 현재 순회 중인 버튼이 선택하려는 버튼(buttonToSelect)과 동일한지 비교하여
// IsSelected 상태를 설정합니다.
// 이렇게 하면 buttonToSelect만 true가 되고 나머지는 false가 됩니다.
// IsSelected 속성의 setter는 필요한 이벤트(OnToggle, OnStateChanged 등)를 발생시킵니다.
buttonInGroup.IsSelected = (buttonInGroup == buttonToSelect);
}
}
/// <summary>
/// 그룹에 등록된 모든 라디오 버튼의 목록을 가져옵니다.
/// </summary>
/// <returns>그룹 내 모든 ToolbarRadioButton의 읽기 전용 컬렉션입니다.</returns>
public IReadOnlyList<ToolbarRadioButton> GetButtons()
{
return _buttons.AsReadOnly();
}
/// <summary>
/// 그룹 내 버튼들의 초기 선택 상태를 설정합니다.
/// 주로 ToolbarModel에서 라디오 버튼들을 추가한 후 호출될 수 있습니다.
/// initialState가 true인 버튼이 있다면 해당 버튼을, 없다면 첫 번째 버튼을 선택합니다.
/// </summary>
internal void InitializeSelection()
{
if (!_buttons.Any()) return;
ToolbarRadioButton buttonToSelectInitially = _buttons.FirstOrDefault(b => b.IsSelected);
if (buttonToSelectInitially != null)
{
// initialState가 true로 설정된 버튼이 있다면, 해당 버튼으로 최종 선택 상태를 확정합니다.
// (다른 initialState=true 버튼이 실수로 여러 개 있었을 경우를 대비하여 명확히 하나만 선택되도록 함)
SetSelected(buttonToSelectInitially);
}
else
{
// IsSelected가 true인 버튼이 하나도 없다면, 그룹의 첫 번째 버튼을 기본으로 선택합니다.
// (라디오 그룹은 일반적으로 항상 하나가 선택되어 있는 상태를 유지하려 함)
SetSelected(_buttons[0]);
}
}
}
}