using System; namespace UVC.UI.Toolbar.Model { /// /// 클릭할 때마다 선택(On) 또는 해제(Off) 상태가 전환되는 토글 버튼입니다. /// ToolbarButtonBase를 상속받으며, 추가적으로 선택 상태(IsSelected)와 /// 해제 상태일 때의 아이콘 경로(OffIconSpritePath), 상태 변경 시 호출될 콜백(OnToggle)을 관리합니다. /// /// /// View 레이어(예: ToolbarView)에서는 이 모델에 해당하는 UI 요소(예: UnityEngine.UI.Toggle)를 생성하고, /// 사용자가 UI 토글을 조작하면 이 모델의 ExecuteClick 메서드를 호출하거나 IsSelected 속성을 직접 변경하여 /// 모델과 UI의 상태를 동기화합니다. IsSelected 속성이 변경되면 OnStateChanged 및 OnToggleStateChanged 이벤트가 발생하여 /// View가 아이콘(선택/해제 상태에 따라 IconSpritePath 또는 OffIconSpritePath 사용) 및 기타 시각적 요소를 업데이트합니다. /// /// /// /// // Toolbar 또는 ToolbarModel 등에서 ToolbarToggleButton 생성 및 사용 예시 /// /// // 1. 토글 상태 변경 시 실행될 액션 정의 (OnToggle 콜백용) /// Action handleMuteToggle = (isMuted) => /// { /// UnityEngine.Debug.Log(isMuted ? "음소거됨" : "음소거 해제됨"); /// // 여기에 실제 음소거/해제 로직 구현 /// }; /// /// // 2. 토글 버튼 클릭 시 실행될 커맨드 정의 (선택 사항, 주로 상태 변경 후 추가 작업) /// // 이 커맨드는 IsSelected 상태가 변경된 *후에* ExecuteClick 내부에서 호출됩니다. /// // 커맨드 파라미터로 현재 IsSelected 상태를 받고 싶다면 ActionCommand 사용 가능. /// ICommand muteCommand = new ActionCommand((IsSelected) => /// { /// UnityEngine.Debug.Log($"음소거 버튼 커맨드 실행됨. 현재 선택 상태: {IsSelected}"); /// }); /// /// // 3. ToolbarToggleButton 인스턴스 생성 및 속성 설정 /// ToolbarToggleButton muteToggleButton = new ToolbarToggleButton /// { /// Text = "button_mute", // 버튼 텍스트 (다국어 키) /// IconSpritePath = "icons/toolbar/sound_on_icon", // 선택(On) 상태 아이콘 /// OffIconSpritePath = "icons/toolbar/sound_off_icon", // 해제(Off) 상태 아이콘 /// Tooltip = "tooltip_mute_button", // 툴팁 (다국어 키) /// IsSelected = false, // 초기 상태는 해제(Off) /// OnToggle = handleMuteToggle, // 상태 변경 시 콜백 할당 /// ClickCommand = muteCommand, // 클릭 커맨드 할당 /// IsEnabled = true // 버튼 활성화 상태 /// }; /// /// // 4. 생성된 버튼 모델을 ToolbarModel에 추가 /// // toolbarModel.AddItem(muteToggleButton); /// // 또는 /// // toolbarModel.AddToggleButton("button_mute", false, "icons/toolbar/sound_on_icon", "icons/toolbar/sound_off_icon", handleMuteToggle, muteCommand, "tooltip_mute_button"); /// /// // 5. 버튼 상태 프로그래밍 방식으로 변경 예시 /// // muteToggleButton.IsSelected = true; // 버튼을 선택 상태로 변경 (OnToggle 콜백 및 이벤트 발생) /// /// public class ToolbarToggleButton : ToolbarButtonBase { /// /// 버튼의 선택 상태(IsSelected)가 변경될 때 발생하는 이벤트입니다. /// 변경된 IsSelected 값을 파라미터로 전달합니다. /// View에서 이 이벤트를 구독하여 UI의 시각적 상태(예: Toggle 컴포넌트의 isOn 상태)를 업데이트할 수 있습니다. /// OnStateChanged 이벤트와 별개로, IsSelected 상태 변경에 좀 더 특화된 알림입니다. /// public event Action OnToggleStateChanged; // IsSelected 변경 시 IsSelected 값을 전달하는 이벤트 protected string _offIconSpritePath; /// /// 버튼이 선택되지 않은(해제된, Off) 상태일 때 표시될 아이콘의 Resources 폴더 내 경로입니다. /// 이 값이 변경되면 OnStateChanged 이벤트가 발생하여 View가 아이콘을 업데이트할 수 있습니다. /// 선택(On) 상태일 때는 ToolbarButtonBase의 IconSpritePath가 사용됩니다. /// public string OffIconSpritePath { get => _offIconSpritePath; set { if (_offIconSpritePath != value) { _offIconSpritePath = value; NotifyStateChanged();// 아이콘 경로 변경 시 전체 상태 변경으로 간주 } } } private bool _isSelected; /// /// 버튼의 현재 선택 상태를 나타냅니다. true이면 선택(On)된 상태, false이면 해제(Off)된 상태입니다. /// 이 속성 값이 변경되면 OnStateChanged 이벤트와 OnToggleStateChanged 이벤트가 발생하며, /// OnToggle 콜백이 호출됩니다. /// public bool IsSelected { get => _isSelected; set { if (_isSelected != value) { _isSelected = value; OnToggle?.Invoke(_isSelected); // OnToggle 콜백 호출 OnToggleStateChanged?.Invoke(_isSelected); // IsSelected 값과 함께 이벤트 발생 NotifyStateChanged(); // 일반 상태 변경 이벤트도 발생 } } } /// /// 버튼의 선택 상태(IsSelected)가 변경될 때 호출될 사용자 정의 콜백 액션입니다. /// IsSelected 속성의 setter 내부에서 호출됩니다. /// /// /// ClickCommand와는 별개로, 순수하게 토글 상태 변경에 대한 응답 로직을 정의할 때 유용합니다. /// 예를 들어, UI 상태 변경에 따른 즉각적인 모델 데이터 변경 등에 사용할 수 있습니다. /// public Action OnToggle { get; set; } /// /// 이벤트 발생 여부를 선택하여 선택 상태를 설정합니다. /// UI 업데이트 이벤트(OnToggleStateChanged, OnStateChanged)는 항상 발생하며, /// raiseEvent는 OnToggle 콜백 호출 여부만 제어합니다. /// /// 설정할 선택 상태입니다. /// true이면 OnToggle 콜백을 호출하고, false이면 호출하지 않습니다. public void SetSelected(bool isSelected, bool raiseEvent) { if (_isSelected != isSelected) { _isSelected = isSelected; if (raiseEvent) { OnToggle?.Invoke(_isSelected); } OnToggleStateChanged?.Invoke(_isSelected); NotifyStateChanged(); } } /// /// 버튼 클릭 로직을 실행합니다. /// 토글 버튼의 경우, 클릭 시 IsSelected 상태를 반전시키고, /// ClickCommand가 있다면 현재 IsSelected 상태를 파라미터로 전달하여 실행합니다. /// /// /// 이 파라미터는 일반적으로 사용되지 않거나 무시될 수 있습니다. /// ClickCommand에는 현재 IsSelected 상태가 전달됩니다. /// 만약 외부에서 특정 값을 전달해야 한다면, ClickCommand가 ActionCommand 등으로 정의되어야 합니다. /// public override void ExecuteClick(object parameter = null) { if (!IsEnabled) return; if (parameter is bool newSelectedStateFromUI) { // UI로부터 직접 상태가 전달된 경우 (View의 OnValueChanged 리스너) // IsSelected 프로퍼티 setter가 OnToggle 및 NotifyStateChanged를 호출 IsSelected = newSelectedStateFromUI; } else { // 일반적인 ExecuteClick (파라미터 없거나 bool이 아님) - 기존 토글 로직 IsSelected = !IsSelected; } // ClickCommand 실행. IsSelected 상태가 변경된 *후에* 실행됩니다. // ClickCommand에 현재 선택 상태(IsSelected)를 파라미터로 전달합니다. // 만약 ClickCommand가 파라미터를 받지 않는 ActionCommand라면, 파라미터 없이 실행됩니다. // ClickCommand가 ActionCommand이라면 IsSelected 값이 전달됩니다. // ClickCommand가 ActionCommand라면 IsSelected 값이 object로 박싱되어 전달됩니다. if (ClickCommand != null) { // ClickCommand의 구체적인 타입(제네릭 여부 등)에 따라 파라미터 전달 방식이 달라질 수 있습니다. // 가장 일반적인 경우는 ClickCommand가 현재 상태를 알 수 있도록 하는 것입니다. // ToolbarView에서 연결 시 new ActionCommand((isSelectedParam) => { /* 로직 */ }) 형태로 커맨드를 생성했다면, // isSelectedParam으로 현재 IsSelected 값이 전달됩니다. ClickCommand.Execute(IsSelected); } } /// /// 이 버튼 모델에 연결된 모든 이벤트 핸들러를 정리합니다. /// ToolbarButtonBase의 이벤트 외에 ToolbarToggleButton에 특화된 이벤트(OnToggleStateChanged, OnToggle)를 추가로 정리합니다. /// public override void ClearEventHandlers() { base.ClearEventHandlers(); // 부모 클래스의 이벤트 정리 (OnStateChanged) OnToggleStateChanged = null; OnToggle = null; } } }