394 lines
14 KiB
C#
394 lines
14 KiB
C#
#nullable enable
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using UVC.UI.Commands;
|
|
|
|
namespace UVC.UIToolkit
|
|
{
|
|
/// <summary>
|
|
/// UTKToolBar의 데이터 모델입니다.
|
|
/// 아이템 컬렉션을 관리하고, 라디오 그룹 등록을 자동화합니다.
|
|
/// 기존 ToolbarModel과 동일한 팩토리 API를 제공합니다.
|
|
/// </summary>
|
|
public class UTKToolBarModel : IDisposable
|
|
{
|
|
#region Fields
|
|
|
|
private readonly Dictionary<string, UTKToolBarRadioButtonGroup> _radioGroups = new();
|
|
private bool _disposed;
|
|
|
|
private bool _showTextLabels = false;
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
/// <summary>전체 아이템 목록 (순서 유지)</summary>
|
|
public List<IUTKToolBarItem> Items { get; private set; } = new();
|
|
|
|
#endregion
|
|
|
|
public UTKToolBarModel(bool showTextLabels = false)
|
|
{
|
|
_showTextLabels = showTextLabels;
|
|
}
|
|
|
|
#region Add Methods
|
|
|
|
/// <summary>
|
|
/// 아이템을 모델에 추가합니다.
|
|
/// ToolbarRadioButton이면 자동으로 그룹에 등록합니다.
|
|
/// </summary>
|
|
/// <param name="item">추가할 아이템</param>
|
|
public void AddItem(IUTKToolBarItem item)
|
|
{
|
|
Items.Add(item);
|
|
|
|
if (item is UTKToolBarRadioButtonData radioButton)
|
|
{
|
|
if (!_radioGroups.TryGetValue(radioButton.GroupName, out var group))
|
|
{
|
|
group = new UTKToolBarRadioButtonGroup(radioButton.GroupName);
|
|
_radioGroups.Add(radioButton.GroupName, group);
|
|
}
|
|
group.RegisterButton(radioButton);
|
|
radioButton.RadioGroup = group;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 일반 버튼을 추가합니다.
|
|
/// </summary>
|
|
/// <param name="text">버튼 텍스트 (다국어 키)</param>
|
|
/// <param name="iconPath">아이콘 경로</param>
|
|
/// <param name="command">실행할 명령</param>
|
|
/// <param name="tooltip">툴팁 (다국어 키)</param>
|
|
/// <param name="useMaterialIcon">Material Icon 사용 여부 (기본값: true)</param>
|
|
/// <returns>생성된 버튼 데이터</returns>
|
|
public UTKToolBarStandardButtonData AddStandardButton(
|
|
string text,
|
|
string? iconPath = null,
|
|
ICommand? command = null,
|
|
string? tooltip = null,
|
|
bool useMaterialIcon = true)
|
|
{
|
|
var button = new UTKToolBarStandardButtonData
|
|
{
|
|
Text = text,
|
|
IconPath = iconPath,
|
|
ClickCommand = command,
|
|
Tooltip = tooltip,
|
|
UseMaterialIcon = useMaterialIcon,
|
|
ShowLabel = _showTextLabels
|
|
};
|
|
AddItem(button);
|
|
return button;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 토글 버튼을 추가합니다.
|
|
/// </summary>
|
|
/// <param name="text">버튼 텍스트</param>
|
|
/// <param name="initialState">초기 On/Off 상태</param>
|
|
/// <param name="onIconPath">On 상태 아이콘</param>
|
|
/// <param name="offIconPath">Off 상태 아이콘</param>
|
|
/// <param name="onToggle">토글 콜백</param>
|
|
/// <param name="command">실행할 명령</param>
|
|
/// <param name="tooltip">툴팁</param>
|
|
/// <param name="useMaterialIcon">Material Icon 사용 여부</param>
|
|
/// <returns>생성된 토글 버튼 데이터</returns>
|
|
public UTKToolBarToggleButtonData AddToggleButton(
|
|
string text,
|
|
bool initialState = false,
|
|
string? onIconPath = null,
|
|
string? offIconPath = null,
|
|
Action<bool>? onToggle = null,
|
|
ICommand? command = null,
|
|
string? tooltip = null,
|
|
bool useMaterialIcon = true)
|
|
{
|
|
var button = new UTKToolBarToggleButtonData
|
|
{
|
|
Text = text,
|
|
IconPath = onIconPath,
|
|
OffIconPath = offIconPath,
|
|
OnToggle = onToggle,
|
|
ClickCommand = command,
|
|
Tooltip = tooltip,
|
|
UseMaterialIcon = useMaterialIcon,
|
|
ShowLabel = _showTextLabels
|
|
};
|
|
// IsSelected를 직접 필드에 설정 (이벤트 발생 방지)
|
|
button.SetSelected(initialState, false);
|
|
AddItem(button);
|
|
return button;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 라디오 버튼을 추가합니다.
|
|
/// </summary>
|
|
/// <param name="groupName">라디오 그룹 이름</param>
|
|
/// <param name="text">버튼 텍스트</param>
|
|
/// <param name="initialState">초기 선택 상태</param>
|
|
/// <param name="onIconPath">선택 상태 아이콘</param>
|
|
/// <param name="offIconPath">비선택 상태 아이콘</param>
|
|
/// <param name="onToggle">토글 콜백</param>
|
|
/// <param name="command">실행할 명령</param>
|
|
/// <param name="tooltip">툴팁</param>
|
|
/// <param name="useMaterialIcon">Material Icon 사용 여부</param>
|
|
/// <returns>생성된 라디오 버튼 데이터</returns>
|
|
public UTKToolBarRadioButtonData AddRadioButton(
|
|
string groupName,
|
|
string text,
|
|
bool initialState = false,
|
|
string? onIconPath = null,
|
|
string? offIconPath = null,
|
|
Action<bool>? onToggle = null,
|
|
ICommand? command = null,
|
|
string? tooltip = null,
|
|
bool useMaterialIcon = true)
|
|
{
|
|
var button = new UTKToolBarRadioButtonData(groupName)
|
|
{
|
|
Text = text,
|
|
IconPath = onIconPath,
|
|
OffIconPath = offIconPath,
|
|
OnToggle = onToggle,
|
|
ClickCommand = command,
|
|
Tooltip = tooltip,
|
|
UseMaterialIcon = useMaterialIcon,
|
|
ShowLabel = _showTextLabels
|
|
};
|
|
button.SetSelected(initialState, false);
|
|
AddItem(button);
|
|
|
|
// initialState가 true이면 그룹에서 명시적으로 선택
|
|
if (initialState && _radioGroups.TryGetValue(groupName, out var group))
|
|
{
|
|
group.SetSelected(button, false);
|
|
}
|
|
return button;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 확장 버튼을 추가합니다.
|
|
/// </summary>
|
|
/// <param name="text">버튼 텍스트</param>
|
|
/// <param name="iconPath">아이콘 경로</param>
|
|
/// <param name="command">실행할 명령</param>
|
|
/// <param name="tooltip">툴팁</param>
|
|
/// <param name="updateIconOnSelection">서브 선택 시 아이콘 업데이트 여부</param>
|
|
/// <param name="useMaterialIcon">Material Icon 사용 여부</param>
|
|
/// <returns>생성된 확장 버튼 데이터</returns>
|
|
public UTKToolBarExpandableButtonData AddExpandableButton(
|
|
string text,
|
|
string? iconPath = null,
|
|
ICommand? command = null,
|
|
string? tooltip = null,
|
|
bool updateIconOnSelection = false,
|
|
bool useMaterialIcon = true)
|
|
{
|
|
var button = new UTKToolBarExpandableButtonData
|
|
{
|
|
Text = text,
|
|
IconPath = iconPath,
|
|
ClickCommand = command,
|
|
Tooltip = tooltip,
|
|
UpdateIconOnSelection = updateIconOnSelection,
|
|
UseMaterialIcon = useMaterialIcon,
|
|
ShowLabel = _showTextLabels
|
|
};
|
|
button.SetOriginalText(text);
|
|
AddItem(button);
|
|
return button;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 구분선을 추가합니다.
|
|
/// </summary>
|
|
/// <returns>생성된 구분선 데이터</returns>
|
|
public UTKToolBarSeparatorData AddSeparator()
|
|
{
|
|
var separator = new UTKToolBarSeparatorData();
|
|
AddItem(separator);
|
|
return separator;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region State Management
|
|
|
|
/// <summary>
|
|
/// 라디오 그룹의 특정 버튼을 선택합니다.
|
|
/// </summary>
|
|
/// <param name="groupName">그룹 이름</param>
|
|
/// <param name="buttonToSelect">선택할 버튼. null이면 모두 해제.</param>
|
|
/// <param name="raiseEvent">이벤트 발생 여부</param>
|
|
/// <returns>성공 여부</returns>
|
|
public bool SetRadioButtonSelection(string groupName, UTKToolBarRadioButtonData? buttonToSelect, bool raiseEvent = true)
|
|
{
|
|
if (!_radioGroups.TryGetValue(groupName, out var group))
|
|
{
|
|
UnityEngine.Debug.LogWarning($"SetRadioButtonSelection: 그룹 '{groupName}'을 찾을 수 없습니다.");
|
|
return false;
|
|
}
|
|
|
|
if (buttonToSelect == null)
|
|
{
|
|
group.ClearSelection(raiseEvent);
|
|
}
|
|
else
|
|
{
|
|
group.SetSelected(buttonToSelect, raiseEvent);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 텍스트로 라디오 버튼을 찾아 선택합니다.
|
|
/// </summary>
|
|
/// <param name="groupName">그룹 이름</param>
|
|
/// <param name="buttonText">버튼 텍스트. null이면 모두 해제.</param>
|
|
/// <param name="raiseEvent">이벤트 발생 여부</param>
|
|
/// <returns>선택된 버튼 또는 null</returns>
|
|
public UTKToolBarRadioButtonData? SetRadioButtonSelectionByText(string groupName, string? buttonText, bool raiseEvent = true)
|
|
{
|
|
if (!_radioGroups.TryGetValue(groupName, out var group))
|
|
{
|
|
UnityEngine.Debug.LogWarning($"SetRadioButtonSelectionByText: 그룹 '{groupName}'을 찾을 수 없습니다.");
|
|
return null;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(buttonText))
|
|
{
|
|
group.ClearSelection(raiseEvent);
|
|
return null;
|
|
}
|
|
|
|
var button = group.FindButtonByText(buttonText);
|
|
if (button == null)
|
|
{
|
|
UnityEngine.Debug.LogWarning($"SetRadioButtonSelectionByText: 그룹 '{groupName}'에서 '{buttonText}' 버튼을 찾을 수 없습니다.");
|
|
return null;
|
|
}
|
|
|
|
group.SetSelected(button, raiseEvent);
|
|
return button;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 라디오 그룹 선택 해제.
|
|
/// </summary>
|
|
/// <param name="groupName">그룹 이름</param>
|
|
/// <param name="raiseEvent">이벤트 발생 여부</param>
|
|
/// <returns>성공 여부</returns>
|
|
public bool ClearRadioButtonSelection(string groupName, bool raiseEvent = true)
|
|
{
|
|
return SetRadioButtonSelection(groupName, null, raiseEvent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 토글 버튼 상태 변경.
|
|
/// </summary>
|
|
/// <param name="toggleButton">토글 버튼</param>
|
|
/// <param name="isSelected">설정할 상태</param>
|
|
/// <param name="raiseEvent">이벤트 발생 여부</param>
|
|
public void SetToggleButtonState(UTKToolBarToggleButtonData toggleButton, bool isSelected, bool raiseEvent = true)
|
|
{
|
|
toggleButton.SetSelected(isSelected, raiseEvent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 텍스트로 토글 버튼을 찾아 상태를 변경합니다.
|
|
/// </summary>
|
|
/// <param name="buttonText">버튼 텍스트</param>
|
|
/// <param name="isSelected">설정할 상태</param>
|
|
/// <param name="raiseEvent">이벤트 발생 여부</param>
|
|
/// <returns>찾은 토글 버튼 또는 null</returns>
|
|
public UTKToolBarToggleButtonData? SetToggleButtonStateByText(string buttonText, bool isSelected, bool raiseEvent = true)
|
|
{
|
|
foreach (var item in Items)
|
|
{
|
|
if (item is UTKToolBarToggleButtonData toggleButton && string.Equals(toggleButton.Text, buttonText, StringComparison.Ordinal))
|
|
{
|
|
toggleButton.SetSelected(isSelected, raiseEvent);
|
|
return toggleButton;
|
|
}
|
|
}
|
|
UnityEngine.Debug.LogWarning($"SetToggleButtonStateByText: '{buttonText}' 토글 버튼을 찾을 수 없습니다.");
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 텍스트로 토글 버튼 상태를 조회합니다.
|
|
/// </summary>
|
|
/// <param name="buttonText">버튼 텍스트</param>
|
|
/// <returns>선택 상태. 버튼을 찾지 못하면 false.</returns>
|
|
public bool GetToggleButtonState(string buttonText)
|
|
{
|
|
foreach (var item in Items)
|
|
{
|
|
if (item is UTKToolBarToggleButtonData toggleButton && string.Equals(toggleButton.Text, buttonText, StringComparison.Ordinal))
|
|
{
|
|
return toggleButton.IsSelected;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 라디오 그룹을 가져옵니다.
|
|
/// </summary>
|
|
/// <param name="groupName">그룹 이름</param>
|
|
/// <returns>라디오 그룹 또는 null</returns>
|
|
public UTKToolBarRadioButtonGroup? GetRadioButtonGroup(string groupName)
|
|
{
|
|
return _radioGroups.TryGetValue(groupName, out var group) ? group : null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IDisposable
|
|
|
|
/// <summary>
|
|
/// 모든 아이템과 라디오 그룹을 정리합니다.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 리소스 정리 구현.
|
|
/// </summary>
|
|
/// <param name="disposing">관리 리소스 정리 여부</param>
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if (_disposed) return;
|
|
_disposed = true;
|
|
|
|
if (disposing)
|
|
{
|
|
foreach (var item in Items)
|
|
{
|
|
if (item is IDisposable disposable)
|
|
{
|
|
disposable.Dispose();
|
|
}
|
|
}
|
|
Items.Clear();
|
|
|
|
foreach (var group in _radioGroups.Values)
|
|
{
|
|
group.Dispose();
|
|
}
|
|
_radioGroups.Clear();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|