683 lines
26 KiB
C#
683 lines
26 KiB
C#
#nullable enable
|
|
using System;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using UVC.UIToolkit;
|
|
using UVC.UI.Commands;
|
|
using UVC.Log;
|
|
|
|
namespace UVC.Sample.UIToolkit
|
|
{
|
|
/// <summary>
|
|
/// UTKMenu 샘플 코드
|
|
/// UIToolkit 기반 TopMenu 시스템을 테스트합니다.
|
|
/// </summary>
|
|
public class UTKMenuSample : MonoBehaviour
|
|
{
|
|
[SerializeField] private UIDocument? _uiDocument;
|
|
|
|
[SerializeField]
|
|
[Tooltip("시작 시 적용할 테마")]
|
|
private UTKTheme initialTheme = UTKTheme.Dark;
|
|
|
|
private UTKToggle? _themeToggle;
|
|
private VisualElement? _root;
|
|
private UTKTopMenu? _menuView;
|
|
private UTKTopMenuModel? _menuModel;
|
|
|
|
private UTKTopMenu? _menuView2;
|
|
private UTKTopMenuModel? _menuModel2;
|
|
|
|
private UTKTopMenu? _menuView3;
|
|
private UTKTopMenuModel? _menuModel3;
|
|
|
|
// 상태 관리용
|
|
private bool _canUndo = false;
|
|
private bool _canRedo = false;
|
|
private bool _isFileOpen = false;
|
|
|
|
|
|
private void Start()
|
|
{
|
|
// UIDocument 참조 확인
|
|
var doc = GetComponent<UIDocument>();
|
|
if (doc == null)
|
|
{
|
|
Debug.LogError("UIDocument가 할당되지 않았습니다.");
|
|
return;
|
|
}
|
|
_uiDocument = doc;
|
|
|
|
var toggle = _uiDocument.rootVisualElement.Q<UTKToggle>("toggle");
|
|
if (toggle == null)
|
|
{
|
|
Debug.LogError("UXML에서 UTKToggle을 찾을 수 없습니다.");
|
|
return;
|
|
}
|
|
_themeToggle = toggle;
|
|
|
|
UTKThemeManager.Instance.RegisterRoot(_uiDocument.rootVisualElement);
|
|
UTKThemeManager.Instance.SetTheme(initialTheme);
|
|
|
|
_themeToggle.OnValueChanged += (isOn) =>
|
|
{
|
|
UTKThemeManager.Instance.SetTheme(!isOn ? UTKTheme.Dark : UTKTheme.Light);
|
|
};
|
|
|
|
_root = _uiDocument.rootVisualElement;
|
|
CreateSampleUI();
|
|
}
|
|
|
|
private void CreateSampleUI()
|
|
{
|
|
if (_root == null) return;
|
|
|
|
// 1. UTKTopMenuView 생성
|
|
_menuView = new UTKTopMenu();
|
|
_menuView.style.position = Position.Absolute;
|
|
_menuView.style.top = 0;
|
|
_menuView.style.left = 50;
|
|
|
|
_menuView2 = new UTKTopMenu();
|
|
_menuView2.style.position = Position.Absolute;
|
|
_menuView2.style.top = 0;
|
|
_menuView2.style.left = 0;
|
|
_menuView2.SubMenuOffsetX = 30;
|
|
_menuView2.SubMenuOffsetY = -20;
|
|
_root.Add(_menuView2);
|
|
_root.Add(_menuView);
|
|
|
|
// 세로 정렬 메뉴 (Vertical Orientation + ItemSpacing)
|
|
_menuView3 = new UTKTopMenu();
|
|
_menuView3.Orientation = UTKMenuOrientation.Vertical;
|
|
_menuView3.ItemSpacing = 4f;
|
|
_menuView3.SubMenuOffsetX = -10f;
|
|
_menuView3.SubMenuOffsetY = 4f;
|
|
_menuView3.style.position = Position.Absolute;
|
|
_menuView3.style.top = 50;
|
|
_menuView3.style.left = 0;
|
|
_menuView3.style.width = 120;
|
|
_root.Add(_menuView3);
|
|
|
|
// 2. UTKTopMenuModel 생성 및 메뉴 아이템 추가
|
|
_menuModel = new UTKTopMenuModel();
|
|
_menuModel2 = new UTKTopMenuModel();
|
|
_menuModel3 = new UTKTopMenuModel();
|
|
|
|
CreateMenuItems();
|
|
|
|
// 3. View에 메뉴 생성
|
|
if (_menuView.MenuContainer != null)
|
|
{
|
|
_menuView.CreateMenuItems(_menuModel.MenuItems, _menuView.MenuContainer);
|
|
}
|
|
|
|
if (_menuView2.MenuContainer != null)
|
|
{
|
|
_menuView2.CreateMenuItems(_menuModel2.MenuItems, _menuView2.MenuContainer);
|
|
}
|
|
|
|
if (_menuView3.MenuContainer != null)
|
|
{
|
|
_menuView3.CreateMenuItems(_menuModel3.MenuItems, _menuView3.MenuContainer);
|
|
}
|
|
|
|
// 4. 이벤트 구독
|
|
_menuView.OnMenuItemClicked += HandleMenuItemClicked;
|
|
_menuView2.OnMenuItemClicked += HandleMenuItemClicked2;
|
|
_menuView3.OnMenuItemClicked += HandleMenuItemClicked3;
|
|
|
|
// 5. 상태 테스트 버튼 생성
|
|
CreateTestButtons();
|
|
|
|
ULog.Debug("UTKTopMenu 샘플 UI 생성 완료");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 메뉴 아이템들을 생성합니다.
|
|
/// </summary>
|
|
private void CreateMenuItems()
|
|
{
|
|
if (_menuModel == null || _menuModel2 == null || _menuModel3 == null) return;
|
|
|
|
// 파일 메뉴
|
|
var fileMenu = new UTKMenuItemData("file", "파일");
|
|
fileMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"file_new",
|
|
"새 파일",
|
|
new DebugLogCommand("새 파일 생성"),
|
|
shortcut: "Ctrl+N"
|
|
));
|
|
fileMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"file_open",
|
|
"열기",
|
|
new DebugLogCommand("파일 열기"),
|
|
shortcut: "Ctrl+O"
|
|
));
|
|
fileMenu.AddSubMenuItem(UTKMenuItemData.CreateSeparator());
|
|
fileMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"file_save",
|
|
"저장",
|
|
new DebugLogCommand("파일 저장"),
|
|
isEnabled: false, // 초기에는 비활성화
|
|
shortcut: "Ctrl+S"
|
|
));
|
|
fileMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"file_save_as",
|
|
"다른 이름으로 저장",
|
|
new DebugLogCommand("다른 이름으로 저장"),
|
|
isEnabled: false,
|
|
shortcut: "Ctrl+Shift+S"
|
|
));
|
|
fileMenu.AddSubMenuItem(UTKMenuItemData.CreateSeparator());
|
|
fileMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"file_exit",
|
|
"종료",
|
|
new DebugLogCommand("애플리케이션 종료"),
|
|
shortcut: "Alt+F4"
|
|
));
|
|
_menuModel.AddMenuItem(fileMenu);
|
|
|
|
// 편집 메뉴
|
|
var editMenu = new UTKMenuItemData("edit", "편집");
|
|
editMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"edit_undo",
|
|
"실행 취소",
|
|
new DebugLogCommand("실행 취소"),
|
|
isEnabled: false,
|
|
shortcut: "Ctrl+Z"
|
|
));
|
|
editMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"edit_redo",
|
|
"다시 실행",
|
|
new DebugLogCommand("다시 실행"),
|
|
isEnabled: false,
|
|
shortcut: "Ctrl+Y"
|
|
));
|
|
editMenu.AddSubMenuItem(UTKMenuItemData.CreateSeparator());
|
|
editMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"edit_cut",
|
|
"잘라내기",
|
|
new DebugLogCommand("잘라내기"),
|
|
shortcut: "Ctrl+X"
|
|
));
|
|
editMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"edit_copy",
|
|
"복사",
|
|
new DebugLogCommand("복사"),
|
|
shortcut: "Ctrl+C"
|
|
));
|
|
editMenu.AddSubMenuItem(new UTKMenuItemData(
|
|
"edit_paste",
|
|
"붙여넣기",
|
|
new DebugLogCommand("붙여넣기"),
|
|
shortcut: "Ctrl+V"
|
|
));
|
|
_menuModel.AddMenuItem(editMenu);
|
|
|
|
// 보기 메뉴 (하위 메뉴 테스트)
|
|
var viewMenu = new UTKMenuItemData("view", "보기");
|
|
|
|
var layoutMenu = new UTKMenuItemData("view_layout", "레이아웃");
|
|
layoutMenu.AddSubMenuItem(new UTKMenuItemData("view_layout_default", "기본", new DebugLogCommand("기본 레이아웃")));
|
|
layoutMenu.AddSubMenuItem(new UTKMenuItemData("view_layout_wide", "와이드", new DebugLogCommand("와이드 레이아웃")));
|
|
layoutMenu.AddSubMenuItem(new UTKMenuItemData("view_layout_compact", "컴팩트", new DebugLogCommand("컴팩트 레이아웃")));
|
|
|
|
viewMenu.AddSubMenuItem(layoutMenu);
|
|
viewMenu.AddSubMenuItem(UTKMenuItemData.CreateSeparator());
|
|
viewMenu.AddSubMenuItem(new UTKMenuItemData("view_fullscreen", "전체 화면", new DebugLogCommand("전체 화면 전환"), shortcut: "F11"));
|
|
_menuModel.AddMenuItem(viewMenu);
|
|
|
|
// 도구 메뉴
|
|
var toolsMenu = new UTKMenuItemData("tools", "도구");
|
|
toolsMenu.AddSubMenuItem(new UTKMenuItemData("tools_options", "옵션", new DebugLogCommand("옵션 열기")));
|
|
toolsMenu.AddSubMenuItem(new UTKMenuItemData("tools_settings", "설정", new DebugLogCommand("설정 열기")));
|
|
_menuModel.AddMenuItem(toolsMenu);
|
|
|
|
// 도움말 메뉴
|
|
var helpMenu = new UTKMenuItemData("help", "도움말");
|
|
helpMenu.AddSubMenuItem(new UTKMenuItemData("help_documentation", "문서", new DebugLogCommand("문서 열기"), shortcut: "F1"));
|
|
helpMenu.AddSubMenuItem(UTKMenuItemData.CreateSeparator());
|
|
helpMenu.AddSubMenuItem(new UTKMenuItemData("help_about", "정보", new DebugLogCommand("정보 표시")));
|
|
_menuModel.AddMenuItem(helpMenu);
|
|
|
|
// 이미지 메뉴 (4 depth 테스트)
|
|
var imageMenu = new UTKMenuImageItemData(
|
|
"image_menu",
|
|
UTKMaterialIcons.Settings, // Material Icon 사용
|
|
useMaterialIcon: true,
|
|
imageSize: 24f
|
|
);
|
|
|
|
// Depth 1 아이템
|
|
var depth1Item = new UTKMenuItemData("depth1", "레벨 1 메뉴");
|
|
var depth1Item1 = new UTKMenuItemData("depth11", "레벨 1 1메뉴");
|
|
var depth1Item2 = new UTKMenuItemData("depth12", "레벨 1 2메뉴");
|
|
var depth1Item3 = new UTKMenuItemData("depth13", "레벨 1 3메뉴");
|
|
|
|
// Depth 2 아이템
|
|
var depth2Item = new UTKMenuItemData("depth2", "레벨 2 메뉴");
|
|
var depth2Item1 = new UTKMenuItemData("depth21", "레벨 2 1 메뉴");
|
|
var depth2Item2 = new UTKMenuItemData("depth22", "레벨 2 2 메뉴");
|
|
var depth2Item3 = new UTKMenuItemData("depth23", "레벨 2 3 메뉴");
|
|
|
|
// Depth 3 아이템
|
|
var depth3Item = new UTKMenuItemData("depth3", "레벨 3 메뉴");
|
|
|
|
// Depth 4 아이템들 (실제 액션)
|
|
var depth4Action1 = new UTKMenuItemData("depth4_action1", "액션 1", new DebugLogCommand("4 Depth 액션 1 실행"));
|
|
var depth4Action2 = new UTKMenuItemData("depth4_action2", "액션 2", new DebugLogCommand("4 Depth 액션 2 실행"));
|
|
var depth4Action3 = new UTKMenuItemData("depth4_action3", "액션 3", new DebugLogCommand("4 Depth 액션 3 실행"));
|
|
|
|
// 계층 구조 구성 (역순으로)
|
|
depth3Item.AddSubMenuItem(depth4Action1);
|
|
depth3Item.AddSubMenuItem(depth4Action2);
|
|
depth3Item.AddSubMenuItem(depth4Action3);
|
|
depth2Item.AddSubMenuItem(depth3Item);
|
|
depth1Item.AddSubMenuItem(depth2Item);
|
|
depth1Item.AddSubMenuItem(depth2Item1);
|
|
depth1Item.AddSubMenuItem(depth2Item2);
|
|
depth1Item.AddSubMenuItem(depth2Item3);
|
|
imageMenu.AddSubMenuItem(depth1Item1);
|
|
imageMenu.AddSubMenuItem(depth1Item2);
|
|
imageMenu.AddSubMenuItem(depth1Item3);
|
|
imageMenu.AddSubMenuItem(depth1Item);
|
|
|
|
_menuModel2.AddMenuItem(imageMenu);
|
|
|
|
// === 세로 메뉴 (menuView3) ===
|
|
var vertFileMenu = new UTKMenuItemData("v_file", "파일");
|
|
vertFileMenu.AddSubMenuItem(new UTKMenuItemData("v_file_new", "새 파일", new DebugLogCommand("세로 메뉴: 새 파일"), shortcut: "Ctrl+N"));
|
|
vertFileMenu.AddSubMenuItem(new UTKMenuItemData("v_file_open", "열기", new DebugLogCommand("세로 메뉴: 열기"), shortcut: "Ctrl+O"));
|
|
vertFileMenu.AddSubMenuItem(UTKMenuItemData.CreateSeparator());
|
|
vertFileMenu.AddSubMenuItem(new UTKMenuItemData("v_file_save", "저장", new DebugLogCommand("세로 메뉴: 저장"), shortcut: "Ctrl+S"));
|
|
_menuModel3.AddMenuItem(vertFileMenu);
|
|
|
|
var vertEditMenu = new UTKMenuItemData("v_edit", "편집");
|
|
vertEditMenu.AddSubMenuItem(new UTKMenuItemData("v_edit_undo", "실행 취소", new DebugLogCommand("세로 메뉴: 실행 취소"), shortcut: "Ctrl+Z"));
|
|
vertEditMenu.AddSubMenuItem(new UTKMenuItemData("v_edit_redo", "다시 실행", new DebugLogCommand("세로 메뉴: 다시 실행"), shortcut: "Ctrl+Y"));
|
|
_menuModel3.AddMenuItem(vertEditMenu);
|
|
|
|
var vertViewMenu = new UTKMenuItemData("v_view", "보기");
|
|
vertViewMenu.AddSubMenuItem(new UTKMenuItemData("v_view_fullscreen", "전체 화면", new DebugLogCommand("세로 메뉴: 전체 화면"), shortcut: "F11"));
|
|
_menuModel3.AddMenuItem(vertViewMenu);
|
|
|
|
var vertHelpMenu = new UTKMenuItemData("v_help", "도움말");
|
|
vertHelpMenu.AddSubMenuItem(new UTKMenuItemData("v_help_about", "정보", new DebugLogCommand("세로 메뉴: 정보")));
|
|
_menuModel3.AddMenuItem(vertHelpMenu);
|
|
|
|
ULog.Debug($"메뉴 아이템 생성 완료: {_menuModel.MenuItems.Count}개 최상위 메뉴, 세로 메뉴: {_menuModel3.MenuItems.Count}개");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 테스트 버튼들을 생성합니다.
|
|
/// </summary>
|
|
private void CreateTestButtons()
|
|
{
|
|
if (_root == null) return;
|
|
|
|
// 테스트 버튼 컨테이너
|
|
var buttonContainer = new VisualElement();
|
|
buttonContainer.style.position = Position.Absolute;
|
|
buttonContainer.style.top = 60;
|
|
buttonContainer.style.left = 300;
|
|
buttonContainer.style.flexDirection = FlexDirection.Column;
|
|
buttonContainer.style.width = 250;
|
|
_root.Insert(0, buttonContainer);
|
|
|
|
// 타이틀
|
|
var title = new Label("메뉴 상태 테스트");
|
|
title.style.fontSize = 16;
|
|
title.style.unityFontStyleAndWeight = FontStyle.Bold;
|
|
title.style.marginBottom = 10;
|
|
buttonContainer.Add(title);
|
|
|
|
// 파일 열기/닫기 버튼
|
|
var fileToggleBtn = new Button(() => ToggleFileOpen())
|
|
{
|
|
text = "파일 열기 (Save 활성화)"
|
|
};
|
|
fileToggleBtn.style.marginBottom = 5;
|
|
buttonContainer.Add(fileToggleBtn);
|
|
|
|
// Undo/Redo 토글 버튼
|
|
var undoToggleBtn = new Button(() => ToggleUndoRedo())
|
|
{
|
|
text = "Undo/Redo 활성화"
|
|
};
|
|
undoToggleBtn.style.marginBottom = 5;
|
|
buttonContainer.Add(undoToggleBtn);
|
|
|
|
// 모든 하위 메뉴 닫기
|
|
var closeAllBtn = new Button(() => _menuView?.CloseAllOpenSubMenus())
|
|
{
|
|
text = "모든 하위 메뉴 닫기"
|
|
};
|
|
closeAllBtn.style.marginBottom = 5;
|
|
buttonContainer.Add(closeAllBtn);
|
|
|
|
// 메뉴 아이템 추가
|
|
var addMenuBtn = new Button(() => AddDynamicMenu())
|
|
{
|
|
text = "동적 메뉴 추가"
|
|
};
|
|
addMenuBtn.style.marginBottom = 5;
|
|
buttonContainer.Add(addMenuBtn);
|
|
|
|
// 메뉴 아이템 제거
|
|
var removeMenuBtn = new Button(() => RemoveDynamicMenu())
|
|
{
|
|
text = "동적 메뉴 제거"
|
|
};
|
|
removeMenuBtn.style.marginBottom = 5;
|
|
buttonContainer.Add(removeMenuBtn);
|
|
|
|
// 단축키 변경
|
|
var changeShortcutBtn = new Button(() => ChangeShortcut())
|
|
{
|
|
text = "Save 단축키 변경"
|
|
};
|
|
changeShortcutBtn.style.marginBottom = 5;
|
|
buttonContainer.Add(changeShortcutBtn);
|
|
|
|
// ExecuteCommand 테스트
|
|
var executeCommandBtn = new Button(() => TestExecuteCommand())
|
|
{
|
|
text = "ExecuteCommand 테스트"
|
|
};
|
|
executeCommandBtn.style.marginBottom = 5;
|
|
buttonContainer.Add(executeCommandBtn);
|
|
|
|
// TryGetMenuItemData 테스트
|
|
var getDataBtn = new Button(() => TestTryGetMenuItemData())
|
|
{
|
|
text = "TryGetMenuItemData 테스트"
|
|
};
|
|
getDataBtn.style.marginBottom = 5;
|
|
buttonContainer.Add(getDataBtn);
|
|
|
|
// 상태 표시 레이블
|
|
var statusLabel = new Label();
|
|
statusLabel.style.marginTop = 20;
|
|
statusLabel.style.fontSize = 12;
|
|
statusLabel.style.color = new Color(0.7f, 0.7f, 0.7f);
|
|
buttonContainer.Add(statusLabel);
|
|
|
|
UpdateStatusLabel(statusLabel);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 파일 열기/닫기 상태를 토글합니다.
|
|
/// </summary>
|
|
private void ToggleFileOpen()
|
|
{
|
|
_isFileOpen = !_isFileOpen;
|
|
|
|
var saveItem = _menuModel?.FindMenuItem("file_save");
|
|
var saveAsItem = _menuModel?.FindMenuItem("file_save_as");
|
|
|
|
if (saveItem != null)
|
|
{
|
|
saveItem.IsEnabled = _isFileOpen;
|
|
if (_menuView != null && _menuView.TryGetMenuItemElement("file_save", out var element))
|
|
{
|
|
var button = element.Q<Button>("submenu-button");
|
|
button?.SetEnabled(_isFileOpen);
|
|
}
|
|
}
|
|
|
|
if (saveAsItem != null)
|
|
{
|
|
saveAsItem.IsEnabled = _isFileOpen;
|
|
if (_menuView != null && _menuView.TryGetMenuItemElement("file_save_as", out var element))
|
|
{
|
|
var button = element.Q<Button>("submenu-button");
|
|
button?.SetEnabled(_isFileOpen);
|
|
}
|
|
}
|
|
|
|
ULog.Debug($"파일 상태: {(_isFileOpen ? "열림" : "닫힘")} - Save 메뉴 {(_isFileOpen ? "활성화" : "비활성화")}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Undo/Redo 상태를 토글합니다.
|
|
/// </summary>
|
|
private void ToggleUndoRedo()
|
|
{
|
|
_canUndo = !_canUndo;
|
|
_canRedo = !_canRedo;
|
|
|
|
var undoItem = _menuModel?.FindMenuItem("edit_undo");
|
|
var redoItem = _menuModel?.FindMenuItem("edit_redo");
|
|
|
|
if (undoItem != null)
|
|
{
|
|
undoItem.IsEnabled = _canUndo;
|
|
if (_menuView != null && _menuView.TryGetMenuItemElement("edit_undo", out var element))
|
|
{
|
|
var button = element.Q<Button>("submenu-button");
|
|
button?.SetEnabled(_canUndo);
|
|
}
|
|
}
|
|
|
|
if (redoItem != null)
|
|
{
|
|
redoItem.IsEnabled = _canRedo;
|
|
if (_menuView != null && _menuView.TryGetMenuItemElement("edit_redo", out var element))
|
|
{
|
|
var button = element.Q<Button>("submenu-button");
|
|
button?.SetEnabled(_canRedo);
|
|
}
|
|
}
|
|
|
|
ULog.Debug($"Undo/Redo 상태: {(_canUndo ? "활성화" : "비활성화")}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 동적으로 메뉴를 추가합니다.
|
|
/// </summary>
|
|
private void AddDynamicMenu()
|
|
{
|
|
if (_menuModel == null || _menuView == null) return;
|
|
|
|
// 이미 존재하는지 확인
|
|
if (_menuModel.FindMenuItem("dynamic") != null)
|
|
{
|
|
ULog.Warning("동적 메뉴가 이미 존재합니다.");
|
|
return;
|
|
}
|
|
|
|
var dynamicMenu = new UTKMenuItemData("dynamic", "동적 메뉴");
|
|
dynamicMenu.AddSubMenuItem(new UTKMenuItemData("dynamic_action1", "액션 1", new DebugLogCommand("동적 액션 1")));
|
|
dynamicMenu.AddSubMenuItem(new UTKMenuItemData("dynamic_action2", "액션 2", new DebugLogCommand("동적 액션 2")));
|
|
|
|
_menuModel.AddMenuItem(dynamicMenu);
|
|
|
|
// View 갱신 (기존 메뉴 제거 후 재생성)
|
|
_menuView.ClearMenuItems();
|
|
if (_menuView.MenuContainer != null)
|
|
{
|
|
_menuView.CreateMenuItems(_menuModel.MenuItems, _menuView.MenuContainer);
|
|
}
|
|
|
|
ULog.Debug("동적 메뉴가 추가되었습니다.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 동적 메뉴를 제거합니다.
|
|
/// </summary>
|
|
private void RemoveDynamicMenu()
|
|
{
|
|
if (_menuModel == null || _menuView == null) return;
|
|
|
|
if (_menuModel.RemoveMenuItem("dynamic"))
|
|
{
|
|
// View 갱신
|
|
_menuView.ClearMenuItems();
|
|
if (_menuView.MenuContainer != null)
|
|
{
|
|
_menuView.CreateMenuItems(_menuModel.MenuItems, _menuView.MenuContainer);
|
|
}
|
|
|
|
ULog.Debug("동적 메뉴가 제거되었습니다.");
|
|
}
|
|
else
|
|
{
|
|
ULog.Warning("제거할 동적 메뉴를 찾을 수 없습니다.");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Save 메뉴의 단축키를 변경합니다.
|
|
/// </summary>
|
|
private void ChangeShortcut()
|
|
{
|
|
if (_menuModel == null || _menuView == null) return;
|
|
|
|
var saveItem = _menuModel.FindMenuItem("file_save");
|
|
if (saveItem != null)
|
|
{
|
|
// 단축키 변경
|
|
string newShortcut = saveItem.Shortcut == "Ctrl+S" ? "Ctrl+Shift+S" : "Ctrl+S";
|
|
saveItem.Shortcut = newShortcut;
|
|
|
|
// View 업데이트
|
|
_menuView.UpdateShortcutText("file_save", newShortcut);
|
|
|
|
ULog.Debug($"Save 단축키 변경: {newShortcut}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 상태 레이블을 업데이트합니다.
|
|
/// </summary>
|
|
private void UpdateStatusLabel(Label label)
|
|
{
|
|
label.text = $"파일: {(_isFileOpen ? "열림" : "닫힘")}\n" +
|
|
$"Undo: {(_canUndo ? "가능" : "불가")}\n" +
|
|
$"Redo: {(_canRedo ? "가능" : "불가")}";
|
|
|
|
label.schedule.Execute(() => UpdateStatusLabel(label)).Every(100);
|
|
}
|
|
|
|
/// <summary>
|
|
/// ExecuteCommand 테스트: ItemId로 Command를 직접 실행합니다.
|
|
/// </summary>
|
|
private void TestExecuteCommand()
|
|
{
|
|
if (_menuView == null) return;
|
|
|
|
// file_new는 항상 활성화 → true 반환
|
|
bool result1 = _menuView.ExecuteCommand("file_new");
|
|
ULog.Debug($"ExecuteCommand(\"file_new\"): {result1}");
|
|
|
|
// file_save는 비활성화 시 false 반환
|
|
bool result2 = _menuView.ExecuteCommand("file_save");
|
|
ULog.Debug($"ExecuteCommand(\"file_save\"): {result2} (비활성화 상태이면 false)");
|
|
|
|
// 존재하지 않는 ID → false 반환
|
|
bool result3 = _menuView.ExecuteCommand("not_exist");
|
|
ULog.Debug($"ExecuteCommand(\"not_exist\"): {result3}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// TryGetMenuItemData 테스트: ItemId로 메뉴 데이터를 조회합니다.
|
|
/// </summary>
|
|
private void TestTryGetMenuItemData()
|
|
{
|
|
if (_menuView == null) return;
|
|
|
|
if (_menuView.TryGetMenuItemData("file_save", out var data))
|
|
{
|
|
ULog.Debug($"TryGetMenuItemData(\"file_save\"): " +
|
|
$"DisplayName={data?.DisplayName}, " +
|
|
$"IsEnabled={data?.IsEnabled}, " +
|
|
$"Shortcut={data?.Shortcut}, " +
|
|
$"HasCommand={data?.Command != null}");
|
|
}
|
|
else
|
|
{
|
|
ULog.Debug("TryGetMenuItemData(\"file_save\"): 찾을 수 없음");
|
|
}
|
|
|
|
// 존재하지 않는 ID
|
|
bool found = _menuView.TryGetMenuItemData("not_exist", out _);
|
|
ULog.Debug($"TryGetMenuItemData(\"not_exist\"): {found}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 메뉴 아이템 클릭 핸들러입니다.
|
|
/// </summary>
|
|
private void HandleMenuItemClicked(UTKMenuItemData itemData)
|
|
{
|
|
if (itemData == null) return;
|
|
|
|
ULog.Debug($"메뉴 클릭: {itemData.ItemId} - {itemData.DisplayName}");
|
|
|
|
// Command 실행
|
|
if (itemData.Command != null)
|
|
{
|
|
itemData.Command.Execute(itemData.CommandParameter);
|
|
}
|
|
}
|
|
|
|
private void HandleMenuItemClicked2(UTKMenuItemData itemData)
|
|
{
|
|
if (itemData == null) return;
|
|
|
|
ULog.Debug($"메뉴2 클릭: {itemData.ItemId} - {itemData.DisplayName}");
|
|
|
|
// Command 실행
|
|
if (itemData.Command != null)
|
|
{
|
|
itemData.Command.Execute(itemData.CommandParameter);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 세로 메뉴 클릭 핸들러입니다.
|
|
/// </summary>
|
|
private void HandleMenuItemClicked3(UTKMenuItemData itemData)
|
|
{
|
|
if (itemData == null) return;
|
|
|
|
ULog.Debug($"세로 메뉴 클릭: {itemData.ItemId} - {itemData.DisplayName}");
|
|
|
|
if (itemData.Command != null)
|
|
{
|
|
itemData.Command.Execute(itemData.CommandParameter);
|
|
}
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
// 이벤트 구독 해제
|
|
if (_menuView != null)
|
|
{
|
|
_menuView.OnMenuItemClicked -= HandleMenuItemClicked;
|
|
_menuView.Dispose();
|
|
}
|
|
|
|
if (_menuView2 != null)
|
|
{
|
|
_menuView2.OnMenuItemClicked -= HandleMenuItemClicked2;
|
|
_menuView2.Dispose();
|
|
}
|
|
|
|
if (_menuView3 != null)
|
|
{
|
|
_menuView3.OnMenuItemClicked -= HandleMenuItemClicked3;
|
|
_menuView3.Dispose();
|
|
}
|
|
|
|
// 모델 정리
|
|
_menuModel?.Dispose();
|
|
_menuModel2?.Dispose();
|
|
_menuModel3?.Dispose();
|
|
|
|
ULog.Debug("UTKMenuSample 정리 완료");
|
|
}
|
|
}
|
|
}
|