261 lines
11 KiB
C#
261 lines
11 KiB
C#
using System;
|
|
using UVC.UI.Commands;
|
|
|
|
namespace UVC.UI.Toolbar.Model
|
|
{
|
|
/// <summary>
|
|
/// 툴바에 사용되는 모든 버튼(표준 버튼, 토글 버튼, 확장 버튼 등)의 기본 추상 클래스입니다.
|
|
/// IToolbarItem 인터페이스를 구현하여 툴바 시스템의 일부가 됩니다.
|
|
/// 버튼이 가져야 할 공통적인 속성(예: 텍스트, 아이콘 경로, 활성화 상태, 툴팁 키)과
|
|
/// 기본적인 동작(예: 클릭 시 커맨드 실행, 상태 변경 알림)을 정의합니다.
|
|
///
|
|
/// 이 클래스를 상속받아 특정 유형의 버튼(예: ToolbarStandardButton, ToolbarToggleButton)을 구현할 수 있습니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// // ToolbarButtonBase를 상속받는 사용자 정의 버튼 예시
|
|
/// public class MyCustomButton : ToolbarButtonBase
|
|
/// {
|
|
/// public string CustomProperty { get; set; }
|
|
///
|
|
/// public MyCustomButton(string text, string iconPath, ICommand command, string tooltip = null)
|
|
/// {
|
|
/// Text = text; // 부모 클래스의 Text 속성 사용
|
|
/// IconSpritePath = iconPath; // 부모 클래스의 IconSpritePath 속성 사용
|
|
/// ClickCommand = command; // 부모 클래스의 ClickCommand 속성 사용
|
|
/// Tooltip = tooltip; // 부모 클래스의 Tooltip 속성 사용
|
|
/// IsEnabled = true; // 기본적으로 활성화 상태로 설정
|
|
/// }
|
|
///
|
|
/// public override void ExecuteClick(object parameter = null)
|
|
/// {
|
|
/// if (!IsEnabled) return; // 비활성화 상태면 아무것도 하지 않음
|
|
///
|
|
/// Debug.Log($"MyCustomButton '{Text}' clicked!");
|
|
/// // 기본 클릭 로직 실행 (예: ClickCommand 실행)
|
|
/// base.ExecuteClick(parameter);
|
|
///
|
|
/// // 이 버튼만의 추가적인 로직 수행
|
|
/// // PerformCustomAction();
|
|
/// }
|
|
/// }
|
|
///
|
|
/// // 사용 예
|
|
/// // ICommand saveCommand = new ActionCommand(() => { Debug.Log("Save HandleClick triggered!"); });
|
|
/// // MyCustomButton saveButton = new MyCustomButton("Save", "icons/save_icon", saveCommand, "Save the current file");
|
|
/// // toolbarModel.AddItem(saveButton);
|
|
/// </code>
|
|
/// </example>
|
|
public abstract class ToolbarButtonBase : IToolbarItem
|
|
{
|
|
/// <summary>
|
|
/// 버튼의 상태(예: Text, IconSpritePath, IsEnabled)가 변경되었을 때 발생하는 이벤트입니다.
|
|
/// View 레이어(예: ToolbarView)는 이 이벤트를 구독하여 버튼의 시각적 표현을 업데이트합니다.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// 속성(Text, IconSpritePath, IsEnabled)의 setter 내부에서 자동으로 호출됩니다.
|
|
/// 여러 상태를 한 번에 변경한 후 수동으로 알리고 싶다면 NotifyStateChanged() 메서드를 사용할 수 있습니다.
|
|
/// </remarks>
|
|
public event Action OnStateChanged;
|
|
|
|
/// <summary>
|
|
/// 버튼이 클릭되었을 때 발생하는 이벤트입니다.
|
|
/// ExecuteClick 메서드가 호출될 때 발생합니다.
|
|
/// </summary>
|
|
public event Action OnClicked;
|
|
|
|
protected string _text;
|
|
/// <summary>
|
|
/// 버튼에 표시될 텍스트 또는 텍스트의 다국어 키입니다.
|
|
/// 값이 변경되면 OnStateChanged 이벤트가 발생합니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// button.Text = "새 작업"; // 직접 텍스트 설정
|
|
/// button.Text = "toolbar_button_new_task_key"; // 다국어 키 설정 (LocalizationManager가 이 키를 실제 텍스트로 변환)
|
|
/// </code>
|
|
/// </example>
|
|
public string Text
|
|
{
|
|
get => _text;
|
|
set
|
|
{
|
|
if (_text != value)
|
|
{
|
|
_text = value;
|
|
OnStateChanged?.Invoke();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected string _iconSpritePath;
|
|
/// <summary>
|
|
/// 버튼에 표시될 아이콘의 Resources 폴더 내 경로입니다 (확장자 제외).
|
|
/// 값이 변경되면 OnStateChanged 이벤트가 발생합니다.
|
|
/// 아이콘이 없는 경우 null 또는 빈 문자열로 설정할 수 있습니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// button.IconSpritePath = "ToolbarIcons/OpenIcon"; // Resources/ToolbarIcons/OpenIcon.png (또는 다른 지원 형식)
|
|
/// </code>
|
|
/// </example>
|
|
public string IconSpritePath
|
|
{
|
|
get => _iconSpritePath;
|
|
set
|
|
{
|
|
if (_iconSpritePath != value)
|
|
{
|
|
_iconSpritePath = value;
|
|
OnStateChanged?.Invoke();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected bool _isEnabled = true;
|
|
/// <summary>
|
|
/// 버튼의 활성화 상태를 나타냅니다. true이면 사용자와 상호작용할 수 있고, false이면 비활성화되어 상호작용할 수 없습니다.
|
|
/// 값이 변경되면 OnStateChanged 이벤트가 발생합니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// button.IsEnabled = false; // 버튼 비활성화
|
|
/// if (button.IsEnabled) { /* 버튼 사용 가능 로직 */ }
|
|
/// </code>
|
|
/// </example>
|
|
public bool IsEnabled
|
|
{
|
|
get => _isEnabled;
|
|
set
|
|
{
|
|
if (_isEnabled != value)
|
|
{
|
|
_isEnabled = value;
|
|
OnStateChanged?.Invoke();
|
|
}
|
|
}
|
|
}
|
|
|
|
protected string _tooltip;
|
|
/// <summary>
|
|
/// 버튼에 마우스를 올렸을 때 표시될 툴팁의 텍스트 또는 다국어 키입니다.
|
|
/// Tooltip 변경 시에는 기본적으로 OnStateChanged 이벤트가 발생하지 않지만,
|
|
/// 필요에 따라 View에서 이 값을 직접 참조하여 툴팁을 업데이트할 수 있습니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// button.Tooltip = "tooltip_save_button"; // 다국어 키 사용
|
|
/// button.Tooltip = "클릭하여 문서를 저장합니다."; // 직접 텍스트 사용
|
|
/// </code>
|
|
/// </example>
|
|
public string Tooltip
|
|
{
|
|
get => _tooltip;
|
|
set
|
|
{
|
|
if (_tooltip != value)
|
|
{
|
|
_tooltip = value;
|
|
// Tooltip 변경 시 OnStateChanged를 호출할 필요는 일반적으로 없으나,
|
|
// 만약 UI가 Tooltip 자체를 표시하는 등의 로직이 있다면 필요할 수 있습니다.
|
|
// 여기서는 툴팁 내용이 동적으로 변경되는 경우가 적다고 가정하고 생략합니다.
|
|
// 필요하다면 OnStateChanged?.Invoke(); 추가
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 버튼이 클릭되었을 때 실행될 동작을 정의하는 커맨드 객체입니다.
|
|
/// ICommand 인터페이스를 구현한 객체를 할당합니다 (예: ActionCommand).
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// // ActionCommand를 사용하여 간단한 동작 정의
|
|
/// button.ClickCommand = new ActionCommand(() =>
|
|
/// {
|
|
/// Debug.Log($"'{button.Text}' 버튼이 클릭되었습니다.");
|
|
/// // 특정 기능 수행
|
|
/// });
|
|
///
|
|
/// // 파라미터가 있는 커맨드
|
|
/// button.ClickCommand = new ActionCommand<string>((fileName) =>
|
|
/// {
|
|
/// Debug.Log($"파일 열기: {fileName}");
|
|
/// });
|
|
/// // ExecuteClick 메서드 호출 시 파라미터 전달 필요
|
|
/// // button.ExecuteClick("MyDocument.txt");
|
|
/// </code>
|
|
/// </example>
|
|
public ICommand ClickCommand { get; set; }
|
|
|
|
/// <summary>
|
|
/// 버튼 클릭 로직을 실행합니다.
|
|
/// 이 메서드는 일반적으로 UI 시스템(예: Unity UI의 Button.onClick 이벤트)에 의해 호출되도록 설계됩니다.
|
|
/// 버튼이 활성화(IsEnabled == true)되어 있고 ClickCommand가 할당되어 있다면, 해당 커맨드를 실행합니다.
|
|
/// IUndoableCommand인 경우 UndoRedoManager를 통해 실행하여 Undo/Redo 히스토리에 기록됩니다.
|
|
/// 파생 클래스에서 이 메서드를 재정의하여 특정 버튼 타입에 맞는 추가적인 클릭 동작을 구현할 수 있습니다.
|
|
/// </summary>
|
|
/// <param name="parameter">ClickCommand에 전달할 선택적 파라미터입니다.</param>
|
|
public virtual void ExecuteClick(object parameter = null)
|
|
{
|
|
if (!IsEnabled) return;
|
|
|
|
if (ClickCommand != null)
|
|
{
|
|
// IUndoableCommand인 경우 UndoRedoManager를 통해 실행
|
|
if (ClickCommand is IUndoableCommand undoableCommand)
|
|
{
|
|
// UndoRedoManager가 존재하는지 확인 (Studio 씬에서만 사용 가능)
|
|
var undoRedoManager = UnityEngine.Object.FindAnyObjectByType<UVC.Studio.Manager.UndoRedoManager>();
|
|
if (undoRedoManager != null)
|
|
{
|
|
undoRedoManager.ExecuteCommand(undoableCommand, parameter);
|
|
}
|
|
else
|
|
{
|
|
// UndoRedoManager가 없으면 직접 실행
|
|
ClickCommand.Execute(parameter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 일반 ICommand는 직접 실행
|
|
ClickCommand.Execute(parameter);
|
|
}
|
|
}
|
|
|
|
OnClicked?.Invoke(); // 클릭 이벤트 발생
|
|
}
|
|
|
|
/// <summary>
|
|
/// OnStateChanged 이벤트를 외부에서 강제로 발생시킵니다.
|
|
/// 여러 속성을 변경한 후 한 번에 UI 업데이트를 트리거하거나,
|
|
/// 내부 상태 변경이 속성 변경을 통하지 않고 발생했을 때 유용합니다.
|
|
/// </summary>
|
|
/// <example>
|
|
/// <code>
|
|
/// public void UpdateButtonAppearance(string newText, string newIcon)
|
|
/// {
|
|
/// _text = newText; // 직접 필드 값 변경 (setter의 OnStateChanged 호출 안됨)
|
|
/// _iconSpritePath = newIcon; // 직접 필드 값 변경
|
|
/// NotifyStateChanged(); // 수동으로 상태 변경 알림
|
|
/// }
|
|
/// </code>
|
|
/// </example>
|
|
public void NotifyStateChanged()
|
|
{
|
|
OnStateChanged?.Invoke();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 이 버튼 모델에 연결된 모든 이벤트 핸들러를 정리(구독 해제)합니다.
|
|
/// 주로 View가 파괴되거나 UI가 재생성될 때 호출되어 메모리 누수를 방지합니다.
|
|
/// 파생 클래스에서는 이 메서드를 재정의하여 해당 클래스에 특화된 이벤트를 추가로 정리해야 합니다.
|
|
/// </summary>
|
|
public virtual void ClearEventHandlers()
|
|
{
|
|
OnStateChanged = null;
|
|
OnClicked = null;
|
|
}
|
|
}
|
|
} |