176 lines
9.0 KiB
C#
176 lines
9.0 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.AddChild(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>
|
|
/// <param name="raiseEvent">true이면 상태 변경 이벤트(OnToggle, OnStateChanged 등)를 발생시키고, false이면 이벤트 없이 상태만 변경합니다. 기본값은 true입니다.</param>
|
|
public void SetSelected(ToolbarRadioButton buttonToSelect, bool raiseEvent = true)
|
|
{
|
|
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가 됩니다.
|
|
bool shouldBeSelected = (buttonInGroup == buttonToSelect);
|
|
buttonInGroup.SetSelected(shouldBeSelected, raiseEvent);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 그룹 내 모든 라디오 버튼의 선택을 해제합니다.
|
|
/// 이 메서드를 호출하면 그룹 내 어떤 버튼도 선택되지 않은 상태가 됩니다.
|
|
/// </summary>
|
|
/// <param name="raiseEvent">true이면 상태 변경 이벤트(OnToggle, OnStateChanged 등)를 발생시키고, false이면 이벤트 없이 상태만 변경합니다. 기본값은 true입니다.</param>
|
|
public void ClearSelection(bool raiseEvent = true)
|
|
{
|
|
SelectedButton = null;
|
|
foreach (var buttonInGroup in _buttons)
|
|
{
|
|
buttonInGroup.SetSelected(false, raiseEvent);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 그룹에 등록된 모든 라디오 버튼의 목록을 가져옵니다.
|
|
/// </summary>
|
|
/// <returns>그룹 내 모든 ToolbarRadioButton의 읽기 전용 컬렉션입니다.</returns>
|
|
public IReadOnlyList<ToolbarRadioButton> GetButtons()
|
|
{
|
|
return _buttons.AsReadOnly();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 텍스트로 그룹 내 라디오 버튼을 찾습니다.
|
|
/// </summary>
|
|
/// <param name="buttonText">찾을 버튼의 텍스트입니다.</param>
|
|
/// <returns>해당 텍스트를 가진 라디오 버튼입니다. 찾지 못하면 null을 반환합니다.</returns>
|
|
public ToolbarRadioButton FindButtonByText(string buttonText)
|
|
{
|
|
return _buttons.FirstOrDefault(b => b.Text == buttonText);
|
|
}
|
|
|
|
/// <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인 버튼이 하나도 없다면
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|