diff --git a/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs b/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs index c1cec978..0054035d 100644 --- a/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs +++ b/NewUI/Config/Debugger/DebuggerShortcutsConfig.cs @@ -3,157 +3,199 @@ using Mesen.ViewModels; using ReactiveUI.Fody.Helpers; using System; using System.Collections.Generic; +using System.Text.Json.Serialization; namespace Mesen.Config { - public class DebuggerShortcutsConfig + public class DebuggerShortcutsConfig : IJsonOnDeserialized { + private List _shortcuts = new(); + private Dictionary _lookup = new(); + + public DebuggerShortcutsConfig() + { + Init(); + } + + public List Shortcuts + { + get => _shortcuts; + set + { + _shortcuts = value; + InitLookup(); + } + } + + private void InitLookup() + { + _lookup = new(); + foreach(DebuggerShortcutInfo shortcut in _shortcuts) { + _lookup[shortcut.Shortcut] = shortcut; + } + } + public DbgShortKeys Get(DebuggerShortcut shortcut) { - DbgShortKeys? binding = Shortcuts.Find(s => s.Shortcut == shortcut)?.KeyBinding; - if(binding == null) { + if(_lookup.TryGetValue(shortcut, out DebuggerShortcutInfo? info)) { + return info.KeyBinding; + } else { throw new Exception("Invalid shortcut"); } - return binding; } internal DebuggerShortcutInfo GetBindable(DebuggerShortcut shortcut) { - DebuggerShortcutInfo? binding = Shortcuts.Find(s => s.Shortcut == shortcut); - if(binding == null) { + if(_lookup.TryGetValue(shortcut, out DebuggerShortcutInfo? info)) { + return info; + } else { throw new Exception("Invalid shortcut"); } - return binding; } - public List Shortcuts { get; set; } = new() { + private void Add(DebuggerShortcutInfo info) + { + if(!_lookup.ContainsKey(info.Shortcut)) { + Shortcuts.Add(info); + _lookup[info.Shortcut] = info; + } + } + + public void OnDeserialized() + { + Init(); + } + + private void Init() + { //Shared - new() { Shortcut = DebuggerShortcut.IncreaseFontSize, KeyBinding = new(KeyModifiers.Control, Key.OemPlus) }, - new() { Shortcut = DebuggerShortcut.DecreaseFontSize, KeyBinding = new(KeyModifiers.Control, Key.OemMinus) }, - new() { Shortcut = DebuggerShortcut.ResetFontSize, KeyBinding = new(KeyModifiers.Control, Key.D0) }, + Add(new() { Shortcut = DebuggerShortcut.IncreaseFontSize, KeyBinding = new(KeyModifiers.Control, Key.OemPlus) }); + Add(new() { Shortcut = DebuggerShortcut.DecreaseFontSize, KeyBinding = new(KeyModifiers.Control, Key.OemMinus) }); + Add(new() { Shortcut = DebuggerShortcut.ResetFontSize, KeyBinding = new(KeyModifiers.Control, Key.D0) }); - new() { Shortcut = DebuggerShortcut.GoTo, KeyBinding = new(KeyModifiers.Control, Key.G) }, + Add(new() { Shortcut = DebuggerShortcut.GoTo, KeyBinding = new(KeyModifiers.Control, Key.G) }); - new() { Shortcut = DebuggerShortcut.Find, KeyBinding = new(KeyModifiers.Control, Key.F) }, - new() { Shortcut = DebuggerShortcut.FindNext, KeyBinding = new(Key.F3) }, - new() { Shortcut = DebuggerShortcut.FindPrev, KeyBinding = new(KeyModifiers.Shift, Key.F3) }, + Add(new() { Shortcut = DebuggerShortcut.Find, KeyBinding = new(KeyModifiers.Control, Key.F) }); + Add(new() { Shortcut = DebuggerShortcut.FindNext, KeyBinding = new(Key.F3) }); + Add(new() { Shortcut = DebuggerShortcut.FindPrev, KeyBinding = new(KeyModifiers.Shift, Key.F3) }); - new() { Shortcut = DebuggerShortcut.Undo, KeyBinding = new(KeyModifiers.Control, Key.Z) }, - new() { Shortcut = DebuggerShortcut.Copy, KeyBinding = new(KeyModifiers.Control, Key.C) }, - new() { Shortcut = DebuggerShortcut.Cut, KeyBinding = new(KeyModifiers.Control, Key.X) }, - new() { Shortcut = DebuggerShortcut.Paste, KeyBinding = new(KeyModifiers.Control, Key.V) }, - new() { Shortcut = DebuggerShortcut.SelectAll, KeyBinding = new(KeyModifiers.Control, Key.A) }, + Add(new() { Shortcut = DebuggerShortcut.Undo, KeyBinding = new(KeyModifiers.Control, Key.Z) }); + Add(new() { Shortcut = DebuggerShortcut.Copy, KeyBinding = new(KeyModifiers.Control, Key.C) }); + Add(new() { Shortcut = DebuggerShortcut.Cut, KeyBinding = new(KeyModifiers.Control, Key.X) }); + Add(new() { Shortcut = DebuggerShortcut.Paste, KeyBinding = new(KeyModifiers.Control, Key.V) }); + Add(new() { Shortcut = DebuggerShortcut.SelectAll, KeyBinding = new(KeyModifiers.Control, Key.A) }); - new() { Shortcut = DebuggerShortcut.Refresh, KeyBinding = new(Key.F5) }, + Add(new() { Shortcut = DebuggerShortcut.Refresh, KeyBinding = new(Key.F5) }); - new() { Shortcut = DebuggerShortcut.MarkAsCode, KeyBinding = new(KeyModifiers.Control, Key.D1) }, - new() { Shortcut = DebuggerShortcut.MarkAsData, KeyBinding = new(KeyModifiers.Control, Key.D2) }, - new() { Shortcut = DebuggerShortcut.MarkAsUnidentified, KeyBinding = new(KeyModifiers.Control, Key.D3) }, + Add(new() { Shortcut = DebuggerShortcut.MarkAsCode, KeyBinding = new(KeyModifiers.Control, Key.D1) }); + Add(new() { Shortcut = DebuggerShortcut.MarkAsData, KeyBinding = new(KeyModifiers.Control, Key.D2) }); + Add(new() { Shortcut = DebuggerShortcut.MarkAsUnidentified, KeyBinding = new(KeyModifiers.Control, Key.D3) }); - new() { Shortcut = DebuggerShortcut.GoToAll, KeyBinding = new(KeyModifiers.Control, Key.OemComma) }, + Add(new() { Shortcut = DebuggerShortcut.GoToAll, KeyBinding = new(KeyModifiers.Control, Key.OemComma) }); - new() { Shortcut = DebuggerShortcut.ZoomIn, KeyBinding = new(KeyModifiers.Control, Key.OemPlus) }, - new() { Shortcut = DebuggerShortcut.ZoomOut, KeyBinding = new(KeyModifiers.Control, Key.OemMinus) }, + Add(new() { Shortcut = DebuggerShortcut.ZoomIn, KeyBinding = new(KeyModifiers.Control, Key.OemPlus) }); + Add(new() { Shortcut = DebuggerShortcut.ZoomOut, KeyBinding = new(KeyModifiers.Control, Key.OemMinus) }); - new() { Shortcut = DebuggerShortcut.SaveAsPng, KeyBinding = new(KeyModifiers.Control, Key.S) }, + Add(new() { Shortcut = DebuggerShortcut.SaveAsPng, KeyBinding = new(KeyModifiers.Control, Key.S) }); - new() { Shortcut = DebuggerShortcut.CodeWindow_EditInMemoryViewer, KeyBinding = new(Key.F1) }, - new() { Shortcut = DebuggerShortcut.MemoryViewer_ViewInDisassembly, KeyBinding = new() }, + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_EditInMemoryViewer, KeyBinding = new(Key.F1) }); + Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_ViewInDisassembly, KeyBinding = new() }); - new() { Shortcut = DebuggerShortcut.OpenAssembler, KeyBinding = new(KeyModifiers.Control, Key.U) }, - new() { Shortcut = DebuggerShortcut.OpenDebugger, KeyBinding = new(KeyModifiers.Control, Key.D) }, - new() { Shortcut = DebuggerShortcut.OpenSpcDebugger, KeyBinding = new(KeyModifiers.Control, Key.F) }, - new() { Shortcut = DebuggerShortcut.OpenSa1Debugger, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.OpenGsuDebugger, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.OpenNecDspDebugger, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.OpenCx4Debugger, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.OpenGameboyDebugger, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.OpenEventViewer, KeyBinding = new(KeyModifiers.Control, Key.E) }, - new() { Shortcut = DebuggerShortcut.OpenMemoryTools, KeyBinding = new(KeyModifiers.Control, Key.M) }, - new() { Shortcut = DebuggerShortcut.OpenProfiler, KeyBinding = new(KeyModifiers.Control, Key.Y) }, - new() { Shortcut = DebuggerShortcut.OpenScriptWindow, KeyBinding = new(KeyModifiers.Control, Key.N) }, - new() { Shortcut = DebuggerShortcut.OpenTraceLogger, KeyBinding = new(KeyModifiers.Control, Key.J) }, - new() { Shortcut = DebuggerShortcut.OpenRegisterViewer, KeyBinding = new(KeyModifiers.Control, Key.K) }, - new() { Shortcut = DebuggerShortcut.OpenDebugLog, KeyBinding = new(KeyModifiers.Control, Key.B) }, + Add(new() { Shortcut = DebuggerShortcut.OpenAssembler, KeyBinding = new(KeyModifiers.Control, Key.U) }); + Add(new() { Shortcut = DebuggerShortcut.OpenDebugger, KeyBinding = new(KeyModifiers.Control, Key.D) }); + Add(new() { Shortcut = DebuggerShortcut.OpenSpcDebugger, KeyBinding = new(KeyModifiers.Control, Key.F) }); + Add(new() { Shortcut = DebuggerShortcut.OpenSa1Debugger, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.OpenGsuDebugger, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.OpenNecDspDebugger, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.OpenCx4Debugger, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.OpenGameboyDebugger, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.OpenEventViewer, KeyBinding = new(KeyModifiers.Control, Key.E) }); + Add(new() { Shortcut = DebuggerShortcut.OpenMemoryTools, KeyBinding = new(KeyModifiers.Control, Key.M) }); + Add(new() { Shortcut = DebuggerShortcut.OpenProfiler, KeyBinding = new(KeyModifiers.Control, Key.Y) }); + Add(new() { Shortcut = DebuggerShortcut.OpenScriptWindow, KeyBinding = new(KeyModifiers.Control, Key.N) }); + Add(new() { Shortcut = DebuggerShortcut.OpenTraceLogger, KeyBinding = new(KeyModifiers.Control, Key.J) }); + Add(new() { Shortcut = DebuggerShortcut.OpenRegisterViewer, KeyBinding = new(KeyModifiers.Control, Key.K) }); + Add(new() { Shortcut = DebuggerShortcut.OpenDebugLog, KeyBinding = new(KeyModifiers.Control, Key.B) }); - new() { Shortcut = DebuggerShortcut.OpenTilemapViewer, KeyBinding = new(KeyModifiers.Control, Key.D1) }, - new() { Shortcut = DebuggerShortcut.OpenTileViewer, KeyBinding = new(KeyModifiers.Control, Key.D2) }, - new() { Shortcut = DebuggerShortcut.OpenSpriteViewer, KeyBinding = new(KeyModifiers.Control, Key.D3) }, - new() { Shortcut = DebuggerShortcut.OpenPaletteViewer, KeyBinding = new(KeyModifiers.Control, Key.D4) }, + Add(new() { Shortcut = DebuggerShortcut.OpenTilemapViewer, KeyBinding = new(KeyModifiers.Control, Key.D1) }); + Add(new() { Shortcut = DebuggerShortcut.OpenTileViewer, KeyBinding = new(KeyModifiers.Control, Key.D2) }); + Add(new() { Shortcut = DebuggerShortcut.OpenSpriteViewer, KeyBinding = new(KeyModifiers.Control, Key.D3) }); + Add(new() { Shortcut = DebuggerShortcut.OpenPaletteViewer, KeyBinding = new(KeyModifiers.Control, Key.D4) }); //Debugger window - new() { Shortcut = DebuggerShortcut.Reset, KeyBinding = new(KeyModifiers.Control, Key.R) }, - new() { Shortcut = DebuggerShortcut.PowerCycle, KeyBinding = new(KeyModifiers.Control, Key.T) }, - new() { Shortcut = DebuggerShortcut.ReloadRom, KeyBinding = new() }, + Add(new() { Shortcut = DebuggerShortcut.Reset, KeyBinding = new(KeyModifiers.Control, Key.R) }); + Add(new() { Shortcut = DebuggerShortcut.PowerCycle, KeyBinding = new(KeyModifiers.Control, Key.T) }); + Add(new() { Shortcut = DebuggerShortcut.ReloadRom, KeyBinding = new() }); - new() { Shortcut = DebuggerShortcut.Continue, KeyBinding = new(Key.F5) }, - new() { Shortcut = DebuggerShortcut.Break, KeyBinding = new(KeyModifiers.Control | KeyModifiers.Alt, Key.Cancel) }, - new() { Shortcut = DebuggerShortcut.ToggleBreakContinue, KeyBinding = new(Key.Escape) }, - new() { Shortcut = DebuggerShortcut.StepInto, KeyBinding = new(Key.F11) }, - new() { Shortcut = DebuggerShortcut.StepOver, KeyBinding = new(Key.F10) }, - new() { Shortcut = DebuggerShortcut.StepOut, KeyBinding = new(KeyModifiers.Shift, Key.F11) }, - new() { Shortcut = DebuggerShortcut.StepBack, KeyBinding = new(KeyModifiers.Shift, Key.F10) }, + Add(new() { Shortcut = DebuggerShortcut.Continue, KeyBinding = new(Key.F5) }); + Add(new() { Shortcut = DebuggerShortcut.Break, KeyBinding = new(KeyModifiers.Control | KeyModifiers.Alt, Key.Cancel) }); + Add(new() { Shortcut = DebuggerShortcut.ToggleBreakContinue, KeyBinding = new(Key.Escape) }); + Add(new() { Shortcut = DebuggerShortcut.StepInto, KeyBinding = new(Key.F11) }); + Add(new() { Shortcut = DebuggerShortcut.StepOver, KeyBinding = new(Key.F10) }); + Add(new() { Shortcut = DebuggerShortcut.StepOut, KeyBinding = new(KeyModifiers.Shift, Key.F11) }); + Add(new() { Shortcut = DebuggerShortcut.StepBack, KeyBinding = new(KeyModifiers.Shift, Key.F10) }); - new() { Shortcut = DebuggerShortcut.RunCpuCycle, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.RunPpuCycle, KeyBinding = new(Key.F6) }, - new() { Shortcut = DebuggerShortcut.RunPpuScanline, KeyBinding = new(Key.F7) }, - new() { Shortcut = DebuggerShortcut.RunPpuFrame, KeyBinding = new(Key.F8) }, + Add(new() { Shortcut = DebuggerShortcut.RunCpuCycle, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.RunPpuCycle, KeyBinding = new(Key.F6) }); + Add(new() { Shortcut = DebuggerShortcut.RunPpuScanline, KeyBinding = new(Key.F7) }); + Add(new() { Shortcut = DebuggerShortcut.RunPpuFrame, KeyBinding = new(Key.F8) }); - new() { Shortcut = DebuggerShortcut.BreakIn, KeyBinding = new(KeyModifiers.Control, Key.B) }, - new() { Shortcut = DebuggerShortcut.BreakOn, KeyBinding = new(KeyModifiers.Alt, Key.B) }, + Add(new() { Shortcut = DebuggerShortcut.BreakIn, KeyBinding = new(KeyModifiers.Control, Key.B) }); + Add(new() { Shortcut = DebuggerShortcut.BreakOn, KeyBinding = new(KeyModifiers.Alt, Key.B) }); - new() { Shortcut = DebuggerShortcut.FindOccurrences, KeyBinding = new(KeyModifiers.Control | KeyModifiers.Shift, Key.F) }, - new() { Shortcut = DebuggerShortcut.GoToProgramCounter, KeyBinding = new(KeyModifiers.Alt, Key.Multiply) }, + Add(new() { Shortcut = DebuggerShortcut.FindOccurrences, KeyBinding = new(KeyModifiers.Control | KeyModifiers.Shift, Key.F) }); + Add(new() { Shortcut = DebuggerShortcut.GoToProgramCounter, KeyBinding = new(KeyModifiers.Alt, Key.Multiply) }); - new() { Shortcut = DebuggerShortcut.CodeWindow_SetNextStatement, KeyBinding = new(KeyModifiers.Control | KeyModifiers.Shift, Key.F10) }, - new() { Shortcut = DebuggerShortcut.CodeWindow_EditSelectedCode, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.CodeWindow_EditSourceFile, KeyBinding = new(Key.F4) }, - new() { Shortcut = DebuggerShortcut.CodeWindow_EditLabel, KeyBinding = new(Key.F2) }, - new() { Shortcut = DebuggerShortcut.CodeWindow_NavigateBack, KeyBinding = new(KeyModifiers.Alt, Key.Left) }, - new() { Shortcut = DebuggerShortcut.CodeWindow_NavigateForward, KeyBinding = new(KeyModifiers.Alt, Key.Right) }, - new() { Shortcut = DebuggerShortcut.CodeWindow_ToggleBreakpoint, KeyBinding = new(Key.F9) }, - new() { Shortcut = DebuggerShortcut.CodeWindow_DisableEnableBreakpoint, KeyBinding = new(KeyModifiers.Control, Key.F9) }, - new() { Shortcut = DebuggerShortcut.CodeWindow_SwitchView, KeyBinding = new(KeyModifiers.Control, Key.Q) }, + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_SetNextStatement, KeyBinding = new(KeyModifiers.Control | KeyModifiers.Shift, Key.F10) }); + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_EditSelectedCode, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_EditSourceFile, KeyBinding = new(Key.F4) }); + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_EditLabel, KeyBinding = new(Key.F2) }); + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_NavigateBack, KeyBinding = new(KeyModifiers.Alt, Key.Left) }); + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_NavigateForward, KeyBinding = new(KeyModifiers.Alt, Key.Right) }); + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_ToggleBreakpoint, KeyBinding = new(Key.F9) }); + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_DisableEnableBreakpoint, KeyBinding = new(KeyModifiers.Control, Key.F9) }); + Add(new() { Shortcut = DebuggerShortcut.CodeWindow_SwitchView, KeyBinding = new(KeyModifiers.Control, Key.Q) }); - new() { Shortcut = DebuggerShortcut.LabelList_Add, KeyBinding = new(Key.Insert) }, - new() { Shortcut = DebuggerShortcut.LabelList_Edit, KeyBinding = new(Key.F2) }, - new() { Shortcut = DebuggerShortcut.LabelList_Delete, KeyBinding = new(Key.Delete) }, - new() { Shortcut = DebuggerShortcut.LabelList_AddBreakpoint, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.LabelList_AddToWatch, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.LabelList_FindOccurrences, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.LabelList_ViewInCpuMemory, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.LabelList_ViewInMemoryType, KeyBinding = new() }, + Add(new() { Shortcut = DebuggerShortcut.LabelList_Add, KeyBinding = new(Key.Insert) }); + Add(new() { Shortcut = DebuggerShortcut.LabelList_Edit, KeyBinding = new(Key.F2) }); + Add(new() { Shortcut = DebuggerShortcut.LabelList_Delete, KeyBinding = new(Key.Delete) }); + Add(new() { Shortcut = DebuggerShortcut.LabelList_AddBreakpoint, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.LabelList_AddToWatch, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.LabelList_FindOccurrences, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.LabelList_ViewInCpuMemory, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.LabelList_ViewInMemoryType, KeyBinding = new() }); - new() { Shortcut = DebuggerShortcut.BreakpointList_Add, KeyBinding = new(Key.Insert) }, - new() { Shortcut = DebuggerShortcut.BreakpointList_Edit, KeyBinding = new(Key.F2) }, - new() { Shortcut = DebuggerShortcut.BreakpointList_GoToLocation, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.BreakpointList_Delete, KeyBinding = new(Key.Delete) }, + Add(new() { Shortcut = DebuggerShortcut.BreakpointList_Add, KeyBinding = new(Key.Insert) }); + Add(new() { Shortcut = DebuggerShortcut.BreakpointList_Edit, KeyBinding = new(Key.F2) }); + Add(new() { Shortcut = DebuggerShortcut.BreakpointList_GoToLocation, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.BreakpointList_Delete, KeyBinding = new(Key.Delete) }); - new() { Shortcut = DebuggerShortcut.WatchList_Delete, KeyBinding = new(Key.Delete) }, - new() { Shortcut = DebuggerShortcut.WatchList_MoveUp, KeyBinding = new(KeyModifiers.Alt, Key.Up) }, - new() { Shortcut = DebuggerShortcut.WatchList_MoveDown, KeyBinding = new(KeyModifiers.Alt, Key.Down) }, + Add(new() { Shortcut = DebuggerShortcut.WatchList_Delete, KeyBinding = new(Key.Delete) }); + Add(new() { Shortcut = DebuggerShortcut.WatchList_MoveUp, KeyBinding = new(KeyModifiers.Alt, Key.Up) }); + Add(new() { Shortcut = DebuggerShortcut.WatchList_MoveDown, KeyBinding = new(KeyModifiers.Alt, Key.Down) }); - new() { Shortcut = DebuggerShortcut.SaveRom, KeyBinding = new(KeyModifiers.Control, Key.S) }, - new() { Shortcut = DebuggerShortcut.SaveRomAs, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.SaveEditAsIps, KeyBinding = new() }, + Add(new() { Shortcut = DebuggerShortcut.SaveRom, KeyBinding = new(KeyModifiers.Control, Key.S) }); + Add(new() { Shortcut = DebuggerShortcut.SaveRomAs, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.SaveEditAsIps, KeyBinding = new() }); //Memory Tools - //new() { Shortcut = eDebuggerShortcut.MemoryViewer_Freeze, KeyBinding = new(KeyModifiers.Control, Key.Q) }, - //new() { Shortcut = eDebuggerShortcut.MemoryViewer_Unfreeze, KeyBinding = new(KeyModifiers.Control, Key.W) }, - new() { Shortcut = DebuggerShortcut.MemoryViewer_AddToWatch, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.MemoryViewer_EditBreakpoint, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.MemoryViewer_EditLabel, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.MemoryViewer_Import, KeyBinding = new(KeyModifiers.Control, Key.O) }, - new() { Shortcut = DebuggerShortcut.MemoryViewer_Export, KeyBinding = new(KeyModifiers.Control, Key.S) }, - new() { Shortcut = DebuggerShortcut.MemoryViewer_ViewInCpuMemory, KeyBinding = new() }, - new() { Shortcut = DebuggerShortcut.MemoryViewer_ViewInMemoryType, KeyBinding = new() }, + //Add(new() { Shortcut = eDebuggerShortcut.MemoryViewer_Freeze, KeyBinding = new(KeyModifiers.Control, Key.Q) }); + //Add(new() { Shortcut = eDebuggerShortcut.MemoryViewer_Unfreeze, KeyBinding = new(KeyModifiers.Control, Key.W) }); + Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_AddToWatch, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_EditBreakpoint, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_EditLabel, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_Import, KeyBinding = new(KeyModifiers.Control, Key.O) }); + Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_Export, KeyBinding = new(KeyModifiers.Control, Key.S) }); + Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_ViewInCpuMemory, KeyBinding = new() }); + Add(new() { Shortcut = DebuggerShortcut.MemoryViewer_ViewInMemoryType, KeyBinding = new() }); //Script Window - new() { Shortcut = DebuggerShortcut.ScriptWindow_OpenScript, KeyBinding = new(KeyModifiers.Control, Key.N) }, - new() { Shortcut = DebuggerShortcut.ScriptWindow_SaveScript, KeyBinding = new(KeyModifiers.Control, Key.S) }, - new() { Shortcut = DebuggerShortcut.ScriptWindow_RunScript, KeyBinding = new(Key.F5) }, - new() { Shortcut = DebuggerShortcut.ScriptWindow_StopScript, KeyBinding = new(Key.Escape) }, - }; + Add(new() { Shortcut = DebuggerShortcut.ScriptWindow_NewScript, KeyBinding = new(KeyModifiers.Control, Key.N) }); + Add(new() { Shortcut = DebuggerShortcut.ScriptWindow_OpenScript, KeyBinding = new(KeyModifiers.Control, Key.O) }); + Add(new() { Shortcut = DebuggerShortcut.ScriptWindow_SaveScript, KeyBinding = new(KeyModifiers.Control, Key.S) }); + Add(new() { Shortcut = DebuggerShortcut.ScriptWindow_RunScript, KeyBinding = new(Key.F5) }); + Add(new() { Shortcut = DebuggerShortcut.ScriptWindow_StopScript, KeyBinding = new(Key.Escape) }); + } } public enum DebuggerShortcut @@ -253,6 +295,7 @@ namespace Mesen.Config MemoryViewer_Export, MemoryViewer_ViewInCpuMemory, MemoryViewer_ViewInMemoryType, + ScriptWindow_NewScript, ScriptWindow_OpenScript, ScriptWindow_SaveScript, ScriptWindow_RunScript, diff --git a/NewUI/Config/Debugger/ScriptWindowConfig.cs b/NewUI/Config/Debugger/ScriptWindowConfig.cs index c34c0240..e751e006 100644 --- a/NewUI/Config/Debugger/ScriptWindowConfig.cs +++ b/NewUI/Config/Debugger/ScriptWindowConfig.cs @@ -18,7 +18,7 @@ namespace Mesen.Config [Reactive] public int Zoom { get; set; } = 100; - [Reactive] public int CodeWindowHeight { get; set; } = 0; + [Reactive] public double LogWindowHeight { get; set; } = 100; [Reactive] public ScriptStartupBehavior ScriptStartupBehavior { get; set; } = ScriptStartupBehavior.ShowTutorial; [Reactive] public bool SaveScriptBeforeRun { get; set; } = true; diff --git a/NewUI/Debugger/Controls/ActionToolbar.axaml b/NewUI/Debugger/Controls/ActionToolbar.axaml new file mode 100644 index 00000000..30753f84 --- /dev/null +++ b/NewUI/Debugger/Controls/ActionToolbar.axaml @@ -0,0 +1,65 @@ + + + Transparent + Transparent + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NewUI/Debugger/Controls/ActionToolbar.axaml.cs b/NewUI/Debugger/Controls/ActionToolbar.axaml.cs new file mode 100644 index 00000000..b9f365c3 --- /dev/null +++ b/NewUI/Debugger/Controls/ActionToolbar.axaml.cs @@ -0,0 +1,63 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Linq; +using Mesen.Config; +using Mesen.Localization; +using Avalonia.Interactivity; +using Avalonia.Data; +using Mesen.Debugger.ViewModels; +using Avalonia.Threading; +using Mesen.Debugger.Utilities; + +namespace Mesen.Debugger.Controls +{ + public class ActionToolbar : UserControl + { + public static readonly StyledProperty> ItemsProperty = AvaloniaProperty.Register>(nameof(Items)); + private DispatcherTimer _timer; + + public List Items + { + get { return GetValue(ItemsProperty); } + set { SetValue(ItemsProperty, value); } + } + + public ActionToolbar() + { + InitializeComponent(); + _timer = new DispatcherTimer(TimeSpan.FromMilliseconds(100), DispatcherPriority.Normal, (s, e) => UpdateToolbar()); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + if(Design.IsDesignMode) { + return; + } + + _timer.Start(); + } + + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + _timer.Stop(); + } + + private void UpdateToolbar() + { + foreach(object item in Items) { + if(item is ContextMenuAction act) { + act.Update(); + } + } + } + } +} diff --git a/NewUI/Debugger/Controls/MesenTextEditor.cs b/NewUI/Debugger/Controls/MesenTextEditor.cs index fd05d078..739e283d 100644 --- a/NewUI/Debugger/Controls/MesenTextEditor.cs +++ b/NewUI/Debugger/Controls/MesenTextEditor.cs @@ -3,6 +3,7 @@ using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Styling; using AvaloniaEdit; +using AvaloniaEdit.Editing; using System; namespace Mesen.Debugger.Controls @@ -11,7 +12,7 @@ namespace Mesen.Debugger.Controls { Type IStyleable.StyleKey => typeof(TextEditor); - public static readonly StyledProperty TextBindingProperty = AvaloniaProperty.Register(nameof(TextBinding), ""); + public static readonly StyledProperty TextBindingProperty = AvaloniaProperty.Register(nameof(TextBinding), "", defaultBindingMode: Avalonia.Data.BindingMode.TwoWay); public string TextBinding { @@ -36,14 +37,22 @@ namespace Mesen.Debugger.Controls static MesenTextEditor() { TextBindingProperty.Changed.AddClassHandler((x, e) => { - x.Text = (string)e.NewValue!; + if(x.Text != (string?)e.NewValue) { + x.Text = (string)e.NewValue!; + } }); } - public MesenTextEditor() { } + protected override void OnTextChanged(EventArgs e) + { + if(TextBinding != Text) { + TextBinding = Text; + } + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -54,5 +63,78 @@ namespace Mesen.Debugger.Controls { VerticalScrollBarValue = line * TextArea.TextView.DefaultLineHeight; } + + /*public MesenTextEditor() + { + TextArea.TextEntered += TextArea_TextEntered; + TextArea.TextEntering += TextArea_TextEntering; + } + + private CompletionWindow? _completionWindow; + private void TextArea_TextEntering(object? sender, TextInputEventArgs e) + { + if(e.Text?.Length > 0 && _completionWindow != null) { + if(!char.IsLetterOrDigit(e.Text[0])) { + // Whenever a non-letter is typed while the completion window is open, + // insert the currently selected element. + _completionWindow.CompletionList.RequestInsertion(e); + } + } + // Do not set e.Handled=true. + // We still want to insert the character that was typed. + } + + private void TextArea_TextEntered(object? sender, TextInputEventArgs e) + { + if(e.Text == ".") { + // Open code completion after the user has pressed dot: + _completionWindow = new CompletionWindow(TextArea); + IList data = _completionWindow.CompletionList.CompletionData; + data.Add(new MyCompletionData("Item1")); + data.Add(new MyCompletionData("Item2")); + data.Add(new MyCompletionData("Item3")); + _completionWindow.Show(); + + var loc = TextArea.TextView.GetVisualPosition(TextArea.Caret.Position, VisualYPosition.LineBottom); + _completionWindow.Host?.ConfigurePosition(this, PlacementMode.Top, new Point(0,0)); + + _completionWindow.Closed += delegate { + _completionWindow = null; + }; + } + } + + public class MyCompletionData : ICompletionData + { + public MyCompletionData(string text) + { + this.Text = text; + } + + public IBitmap Image + { + get { return null; } + } + + public string Text { get; private set; } + + // Use this property if you want to show a fancy UIElement in the list. + public object Content + { + get { return new TextBlock() { Text = this.Text }; } + } + + public object Description + { + get { return "Description for " + this.Text; } + } + + public double Priority => 1.0; + + public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) + { + textArea.Document.Replace(completionSegment, this.Text); + } + }*/ } } diff --git a/NewUI/Debugger/Utilities/ContextMenuAction.cs b/NewUI/Debugger/Utilities/ContextMenuAction.cs index 8bbdb0d6..ca8069de 100644 --- a/NewUI/Debugger/Utilities/ContextMenuAction.cs +++ b/NewUI/Debugger/Utilities/ContextMenuAction.cs @@ -15,11 +15,16 @@ namespace Mesen.Debugger.Utilities public class ContextMenuAction : ViewModelBase { public ActionType ActionType; + public string? CustomText { get; set; } public string Name { get { + if(ActionType == ActionType.Custom) { + return CustomText ?? ""; + } + string label = ResourceHelper.GetEnumText(ActionType); if(HintText != null) { label += " (" + HintText() + ")"; @@ -106,6 +111,8 @@ namespace Mesen.Debugger.Utilities public enum ActionType { + Custom, + [IconFile("Copy")] Copy, @@ -222,6 +229,31 @@ namespace Mesen.Debugger.Utilities Reset, [IconFile("PowerCycle")] - PowerCycle + PowerCycle, + + [IconFile("Script")] + NewScript, + + [IconFile("MediaPlay")] + RunScript, + + [IconFile("MediaStop")] + StopScript, + + [IconFile("Folder")] + Open, + + [IconFile("SaveFloppy")] + Save, + + SaveAs, + + [IconFile("Exit")] + Exit, + + [IconFile("Help")] + HelpApiReference, + + RecentScripts, } } diff --git a/NewUI/Debugger/Utilities/GridLengthConverter.cs b/NewUI/Debugger/Utilities/GridLengthConverter.cs new file mode 100644 index 00000000..c1781a89 --- /dev/null +++ b/NewUI/Debugger/Utilities/GridLengthConverter.cs @@ -0,0 +1,27 @@ +using Avalonia.Controls; +using Avalonia.Data.Converters; +using System; + +namespace Mesen.Debugger.Utilities +{ + public class GridLengthConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if(value is double val && targetType == typeof(GridLength)) { + return new GridLength(val, GridUnitType.Pixel); + } + + throw new Exception("unsupported"); + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if(value is GridLength s) { + return s.Value; + } + + return 0.0; + } + } +} diff --git a/NewUI/Debugger/ViewModels/DebuggerConfigWindowViewModel.cs b/NewUI/Debugger/ViewModels/DebuggerConfigWindowViewModel.cs index aa437006..d2af5175 100644 --- a/NewUI/Debugger/ViewModels/DebuggerConfigWindowViewModel.cs +++ b/NewUI/Debugger/ViewModels/DebuggerConfigWindowViewModel.cs @@ -15,15 +15,16 @@ namespace Mesen.Debugger.ViewModels public DebuggerConfig Debugger { get; set; } public ScriptWindowConfig Script { get; set; } public DbgIntegrationConfig Integration { get; set; } - [Reactive] public int SelectedIndex { get; set; } + [Reactive] public DebugConfigWindowTab SelectedIndex { get; set; } public List SharedShortcuts { get; set; } = new(); public List MemoryToolsShortcuts { get; set; } = new(); public List ScriptShortcuts { get; set; } = new(); public List DebuggerShortcuts { get; set; } = new(); - public DebuggerConfigWindowViewModel() + public DebuggerConfigWindowViewModel(DebugConfigWindowTab tab) { + SelectedIndex = tab; Debugger = ConfigManager.Config.Debug.Debugger; Font = ConfigManager.Config.Debug.Font; Script = ConfigManager.Config.Debug.ScriptWindow; @@ -168,4 +169,13 @@ namespace Mesen.Debugger.ViewModels ConfigManager.SaveConfig(); } } + + public enum DebugConfigWindowTab + { + Debugger, + ScriptWindow, + FontAndColors, + Integration, + Shortcuts + } } diff --git a/NewUI/Debugger/ViewModels/DebuggerWindowViewModel.cs b/NewUI/Debugger/ViewModels/DebuggerWindowViewModel.cs index aa892720..5943138a 100644 --- a/NewUI/Debugger/ViewModels/DebuggerWindowViewModel.cs +++ b/NewUI/Debugger/ViewModels/DebuggerWindowViewModel.cs @@ -236,11 +236,7 @@ namespace Mesen.Debugger.ViewModels new Separator(), new ContextMenuAction() { ActionType = ActionType.Preferences, - OnClick = () => { - new DebuggerConfigWindow() { - DataContext = new DebuggerConfigWindowViewModel() - }.ShowCenteredDialog((Control)wnd); - } + OnClick = () => DebuggerConfigWindow.Open(DebugConfigWindowTab.Debugger, wnd) }, }; diff --git a/NewUI/Debugger/ViewModels/ScriptWindowViewModel.cs b/NewUI/Debugger/ViewModels/ScriptWindowViewModel.cs index 0720c33c..3015ae41 100644 --- a/NewUI/Debugger/ViewModels/ScriptWindowViewModel.cs +++ b/NewUI/Debugger/ViewModels/ScriptWindowViewModel.cs @@ -1,17 +1,229 @@ using Avalonia.Controls; using Mesen.Config; +using Mesen.Debugger.Utilities; +using Mesen.Debugger.Windows; using Mesen.Interop; +using Mesen.Utilities; using Mesen.ViewModels; +using Mesen.Windows; using ReactiveUI.Fody.Helpers; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; namespace Mesen.Debugger.ViewModels { public class ScriptWindowViewModel : ViewModelBase { + public ScriptWindowConfig Config { get; } = ConfigManager.Config.Debug.ScriptWindow; public FontConfig Font { get; } = ConfigManager.Config.Debug.Font; - public ScriptWindowViewModel(CpuType cpuType, string code) + [Reactive] public string Code { get; set; } = ""; + [Reactive] public string FilePath { get; set; } = ""; + [Reactive] public int ScriptId { get; set; } = -1; + [Reactive] public string Log { get; set; } = ""; + + private string _originalText = ""; + private ScriptWindow? _wnd = null; + + private ContextMenuAction _recentScriptsAction = new(); + + public List FileMenuActions { get; private set; } = new(); + public List ScriptMenuActions { get; private set; } = new(); + public List HelpMenuActions { get; private set; } = new(); + public List ToolbarActions { get; private set; } = new(); + + public ScriptWindowViewModel() { } + + public void InitActions(ScriptWindow wnd) + { + if(wnd == null) { + throw new Exception("Invalid parent window"); + } + + _wnd = wnd; + + _recentScriptsAction = new ContextMenuAction() { + ActionType = ActionType.RecentScripts, + SubActions = new() + }; + _recentScriptsAction.IsEnabled = () => _recentScriptsAction.SubActions.Count > 0; + + ScriptMenuActions = GetScriptMenuAction(); + ToolbarActions = GetScriptMenuAction(); + + FileMenuActions = new() { + new ContextMenuAction() { + ActionType = ActionType.NewScript, + Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.ScriptWindow_NewScript), + OnClick = () => { + new ScriptWindow { DataContext = new ScriptWindowViewModel() }.Show(); + } + }, + new ContextMenuAction() { + ActionType = ActionType.Open, + Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.ScriptWindow_OpenScript), + OnClick = () => OpenScript() + }, + new ContextMenuAction() { + ActionType = ActionType.Save, + Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.ScriptWindow_SaveScript), + OnClick = async () => await SaveScript() + }, + new ContextMenuAction() { + ActionType = ActionType.SaveAs, + OnClick = async () => await SaveAs(Path.GetFileName(FilePath)) + }, + new Separator(), + _recentScriptsAction, + new Separator(), + new ContextMenuAction() { + ActionType = ActionType.Exit, + OnClick = () => _wnd?.Close() + } + }; + + HelpMenuActions = new() { + new ContextMenuAction() { + ActionType = ActionType.HelpApiReference, + OnClick = () => Process.Start(new ProcessStartInfo() { FileName = "https://www.mesen.ca/snes/ApiReference.php", UseShellExecute = true }) + } + }; + + UpdateRecentScriptsMenu(); + DebugShortcutManager.RegisterActions(_wnd, ScriptMenuActions); + DebugShortcutManager.RegisterActions(_wnd, FileMenuActions); + } + + private List GetScriptMenuAction() + { + return new() { + new ContextMenuAction() { + ActionType = ActionType.RunScript, + Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.ScriptWindow_RunScript), + IsEnabled = () => ScriptId < 0, + OnClick = () => { + ScriptId = DebugApi.LoadScript(ScriptName, Code, ScriptId); + } + }, + new ContextMenuAction() { + ActionType = ActionType.StopScript, + Shortcut = () => ConfigManager.Config.Debug.Shortcuts.Get(DebuggerShortcut.ScriptWindow_StopScript), + IsEnabled = () => ScriptId >= 0, + OnClick = () => { + DebugApi.RemoveScript(ScriptId); + ScriptId = -1; + } + }, + new Separator(), + new ContextMenuAction() { + ActionType = ActionType.Preferences, + OnClick = () => DebuggerConfigWindow.Open(DebugConfigWindowTab.ScriptWindow, _wnd) + } + }; + } + + private string ScriptName + { + get + { + if(FilePath != null) { + return Path.GetFileName(FilePath); + } else { + return "unnamed.lua"; + } + } + } + + private string? InitialFolder + { + get + { + if(ConfigManager.Config.Debug.ScriptWindow.RecentScripts.Count > 0) { + return Path.GetDirectoryName(ConfigManager.Config.Debug.ScriptWindow.RecentScripts[0]); + } + return null; + } + } + + private void UpdateRecentScriptsMenu() + { + _recentScriptsAction.SubActions = ConfigManager.Config.Debug.ScriptWindow.RecentScripts.Select(x => new ContextMenuAction() { + ActionType = ActionType.Custom, + CustomText = x, + OnClick = () => LoadScript(x) + }).ToList(); + } + + private async void OpenScript() + { + if(!await SavePrompt()) { + return; + } + + string? filename = await FileDialogHelper.OpenFile(InitialFolder, _wnd, FileDialogHelper.LuaFileExt); + if(filename != null) { + LoadScript(filename); + } + } + + private void AddRecentScript(string filename) + { + ConfigManager.Config.Debug.ScriptWindow.AddRecentScript(filename); + UpdateRecentScriptsMenu(); + } + + private void LoadScript(string filename) + { + if(File.Exists(filename)) { + Code = File.ReadAllText(filename); + FilePath = filename; + _originalText = Code; + AddRecentScript(filename); + } + } + + private async Task SavePrompt() + { + if(_originalText != Code) { + DialogResult result = await MesenMsgBox.Show(_wnd, "You have unsaved changes for this script - would you like to save them?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning); + if(result == DialogResult.Yes) { + return !(await SaveScript()); + } else if(result == DialogResult.Cancel) { + return false; + } + } + return true; + } + + private async Task SaveScript() + { + if(!string.IsNullOrWhiteSpace(FilePath)) { + File.WriteAllText(FilePath, Code, Encoding.UTF8); + _originalText = Code; + return true; + } else { + return await SaveAs("NewScript.lua"); + } + } + + private async Task SaveAs(string newName) + { + string? filename = await FileDialogHelper.SaveFile(InitialFolder, newName, _wnd, FileDialogHelper.LuaFileExt); + if(filename != null) { + FilePath = filename; + File.WriteAllText(FilePath, Code, Encoding.UTF8); + AddRecentScript(filename); + return true; + } else { + return false; + } + } } } diff --git a/NewUI/Debugger/Windows/DebuggerConfigWindow.axaml.cs b/NewUI/Debugger/Windows/DebuggerConfigWindow.axaml.cs index 21034a35..da458bca 100644 --- a/NewUI/Debugger/Windows/DebuggerConfigWindow.axaml.cs +++ b/NewUI/Debugger/Windows/DebuggerConfigWindow.axaml.cs @@ -8,6 +8,8 @@ using System; using System.ComponentModel; using Mesen.Config; using Mesen.Debugger.ViewModels; +using Mesen.Utilities; +using Avalonia.Rendering; namespace Mesen.Debugger.Windows { @@ -32,6 +34,11 @@ namespace Mesen.Debugger.Windows } } + public static void Open(DebugConfigWindowTab tab, IRenderRoot? parent) + { + new DebuggerConfigWindow() { DataContext = new DebuggerConfigWindowViewModel(tab) }.ShowCentered(parent); + } + private void InitializeComponent() { AvaloniaXamlLoader.Load(this); diff --git a/NewUI/Debugger/Windows/DebuggerWindow.axaml b/NewUI/Debugger/Windows/DebuggerWindow.axaml index 3ae1a5a2..8ace82da 100644 --- a/NewUI/Debugger/Windows/DebuggerWindow.axaml +++ b/NewUI/Debugger/Windows/DebuggerWindow.axaml @@ -32,25 +32,11 @@ - - @@ -69,28 +55,8 @@ - - - - - - - - - - - - - + + diff --git a/NewUI/Debugger/Windows/DebuggerWindow.axaml.cs b/NewUI/Debugger/Windows/DebuggerWindow.axaml.cs index 0c9d5e3c..2af876b5 100644 --- a/NewUI/Debugger/Windows/DebuggerWindow.axaml.cs +++ b/NewUI/Debugger/Windows/DebuggerWindow.axaml.cs @@ -21,7 +21,6 @@ namespace Mesen.Debugger.Windows { private DebuggerWindowViewModel _model; private NotificationListener? _listener; - private DispatcherTimer _timer; public DebuggerWindow() { @@ -29,7 +28,6 @@ namespace Mesen.Debugger.Windows #if DEBUG this.AttachDevTools(); #endif - _timer = new DispatcherTimer(TimeSpan.FromMilliseconds(100), DispatcherPriority.Normal, (s, e) => UpdateToolbar()); } private void InitializeComponent() @@ -74,7 +72,6 @@ namespace Mesen.Debugger.Windows return; } - _timer.Start(); _listener = new NotificationListener(); _listener.OnNotification += _listener_OnNotification; UpdateDebugger(); @@ -86,7 +83,6 @@ namespace Mesen.Debugger.Windows return; } - _timer.Stop(); _listener?.Dispose(); _model.Cleanup(); _model.Config.SaveWindowSettings(this); @@ -115,14 +111,5 @@ namespace Mesen.Debugger.Windows { _model.Config.ShowSettingsPanel = !_model.Config.ShowSettingsPanel; } - - private void UpdateToolbar() - { - foreach(object item in _model.ToolbarItems) { - if(item is ContextMenuAction act) { - act.Update(); - } - } - } } } diff --git a/NewUI/Debugger/Windows/ScriptWindow.axaml b/NewUI/Debugger/Windows/ScriptWindow.axaml index dec7afa2..fae9d8f4 100644 --- a/NewUI/Debugger/Windows/ScriptWindow.axaml +++ b/NewUI/Debugger/Windows/ScriptWindow.axaml @@ -7,6 +7,7 @@ xmlns:sys="using:System" xmlns:v="using:Mesen.Views" xmlns:dbg="using:Mesen.Debugger" + xmlns:du="using:Mesen.Debugger.Utilities" xmlns:c="using:Mesen.Controls" xmlns:l="using:Mesen.Localization" xmlns:i="using:Mesen.Interop" @@ -16,7 +17,6 @@ mc:Ignorable="d" d:DesignWidth="700" d:DesignHeight="500" x:Class="Mesen.Debugger.Windows.ScriptWindow" Icon="/Assets/Script.png" - Width="700" Height="500" x:DataType="vm:ScriptWindowViewModel" Title="{l:Translate wndTitle}" > @@ -24,36 +24,47 @@ - - - - - - - - - + + + + + + + + + + + + + - - + + + + + + + + + + + + + - - - - + + diff --git a/NewUI/Debugger/Windows/ScriptWindow.axaml.cs b/NewUI/Debugger/Windows/ScriptWindow.axaml.cs index 1983a487..c983c957 100644 --- a/NewUI/Debugger/Windows/ScriptWindow.axaml.cs +++ b/NewUI/Debugger/Windows/ScriptWindow.axaml.cs @@ -3,12 +3,16 @@ using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.Media; +using Avalonia.Threading; using AvaloniaEdit; using AvaloniaEdit.Highlighting; using AvaloniaEdit.Highlighting.Xshd; +using Mesen.Config; using Mesen.Debugger.Controls; using Mesen.Debugger.ViewModels; using Mesen.Interop; +using System; +using System.ComponentModel; using System.Reflection; using System.Xml; @@ -18,7 +22,9 @@ namespace Mesen.Debugger.Windows { private static IHighlightingDefinition _highlighting; private MesenTextEditor _textEditor; - + private DispatcherTimer _timer; + private ScriptWindowViewModel? _model; + static ScriptWindow() { using XmlReader reader = XmlReader.Create(Assembly.GetExecutingAssembly().GetManifestResourceStream("Mesen.Debugger.HighlightLua.xshd")!); @@ -35,18 +41,44 @@ namespace Mesen.Debugger.Windows _textEditor = this.FindControl("Editor"); _textEditor.SyntaxHighlighting = _highlighting; + _timer = new DispatcherTimer(TimeSpan.FromMilliseconds(100), DispatcherPriority.Normal, (s, e) => UpdateLog()); } - private int _scriptId = -1; - private void OnRunClick(object sender, RoutedEventArgs e) + protected override void OnOpened(EventArgs e) { - _scriptId = DebugApi.LoadScript("test", _textEditor.Text); + if(Design.IsDesignMode) { + return; + } + + _timer.Start(); } - private void OnStopClick(object sender, RoutedEventArgs e) + protected override void OnClosing(CancelEventArgs e) { - if(_scriptId >= 0) { - DebugApi.RemoveScript(_scriptId); + if(Design.IsDesignMode) { + return; + } + + _timer.Stop(); + _model?.Config.SaveWindowSettings(this); + ConfigManager.Config.Save(); + } + + protected override void OnDataContextChanged(EventArgs e) + { + if(DataContext is ScriptWindowViewModel model) { + _model = model; + _model.InitActions(this); + _model.Config.LoadWindowSettings(this); + } else { + throw new Exception("Invalid DataContext"); + } + } + + private void UpdateLog() + { + if(_model?.ScriptId >= 0) { + _model.Log = DebugApi.GetScriptLog(_model.ScriptId); } } diff --git a/NewUI/Localization/resources.en.xml b/NewUI/Localization/resources.en.xml index 1265dea8..9ad2c4b7 100644 --- a/NewUI/Localization/resources.en.xml +++ b/NewUI/Localization/resources.en.xml @@ -1717,6 +1717,18 @@ x == [$150] || y == [10] Run one frame Break in... Break on... + + Run Script + Stop Script + New Script Window + + Open + Save + Save as... + Exit + + API Reference + Recent Scripts \ No newline at end of file diff --git a/NewUI/NewUI.csproj b/NewUI/NewUI.csproj index ed5da2c5..70d39b4a 100644 --- a/NewUI/NewUI.csproj +++ b/NewUI/NewUI.csproj @@ -200,6 +200,9 @@ DebuggerKeyBindingButton + + ActionToolbar.axaml + SpritePreviewPanel.axaml diff --git a/NewUI/Utilities/FileDialogHelper.cs b/NewUI/Utilities/FileDialogHelper.cs index a0df81fc..2c5a050d 100644 --- a/NewUI/Utilities/FileDialogHelper.cs +++ b/NewUI/Utilities/FileDialogHelper.cs @@ -21,6 +21,7 @@ namespace Mesen.Utilities public static string WaveExt = "wav"; public static string MesenSaveStateExt = "mss"; public static string WatchFileExt = "txt"; + public static string LuaFileExt = "lua"; public static async Task OpenFile(string? initialFolder, IRenderRoot? parent, params string[] extensions) { diff --git a/NewUI/Views/MainMenuView.axaml.cs b/NewUI/Views/MainMenuView.axaml.cs index c4a4a386..de038878 100644 --- a/NewUI/Views/MainMenuView.axaml.cs +++ b/NewUI/Views/MainMenuView.axaml.cs @@ -99,9 +99,8 @@ namespace Mesen.Views private void OnScriptWindowClick(object sender, RoutedEventArgs e) { - RomInfo romInfo = EmuApi.GetRomInfo(); new ScriptWindow { - DataContext = new ScriptWindowViewModel(romInfo.ConsoleType.GetMainCpuType(), "") + DataContext = new ScriptWindowViewModel() }.Show(); } @@ -136,9 +135,7 @@ namespace Mesen.Views private void OnDebuggerSettingsClick(object sender, RoutedEventArgs e) { - new DebuggerConfigWindow { - DataContext = new DebuggerConfigWindowViewModel() - }.Show(); + DebuggerConfigWindow.Open(DebugConfigWindowTab.Debugger, VisualRoot); } private void OpenConfig(ConfigWindowTab tab)