Script Window: Add menus, toolbar, etc.

This commit is contained in:
Sour 2021-12-25 12:44:12 -05:00
parent dc2f493cb3
commit 25be764599
19 changed files with 758 additions and 212 deletions

View file

@ -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<DebuggerShortcutInfo> _shortcuts = new();
private Dictionary<DebuggerShortcut, DebuggerShortcutInfo> _lookup = new();
public DebuggerShortcutsConfig()
{
Init();
}
public List<DebuggerShortcutInfo> 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<DebuggerShortcutInfo> 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,

View file

@ -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;

View file

@ -0,0 +1,65 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:l="using:Mesen.Localization"
xmlns:du="using:Mesen.Debugger.Utilities"
mc:Ignorable="d" d:DesignWidth="280" d:DesignHeight="200"
x:Class="Mesen.Debugger.Controls.ActionToolbar"
x:Name="root"
>
<UserControl.Resources>
<Color x:Key="ButtonBackground">Transparent</Color>
<Color x:Key="ButtonBorderBrush">Transparent</Color>
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="Button">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="Padding" Value="1" />
</Style>
<Style Selector="Button:disabled">
<Setter Property="Opacity" Value="0.5" />
</Style>
<Style Selector="Button Image">
<Setter Property="Margin" Value="0" />
<Setter Property="Width" Value="16" />
<Setter Property="Height" Value="16" />
</Style>
<Style Selector="StackPanel Separator">
<Setter Property="Width" Value="2" />
<Setter Property="Height" Value="16" />
<Setter Property="Margin" Value="2 0" />
<Setter Property="Padding" Value="0" />
<Setter Property="Template">
<ControlTemplate>
<Rectangle Stroke="LightGray" StrokeThickness="1" Height="16" Width="1" />
</ControlTemplate>
</Setter>
</Style>
</UserControl.Styles>
<ItemsPresenter DataContext="{Binding ElementName=root}" Items="{Binding Items}">
<ItemsPresenter.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsPresenter.ItemsPanel>
<ItemsPresenter.ItemTemplate>
<DataTemplate DataType="{x:Type du:ContextMenuAction}">
<Button ToolTip.Tip="{Binding Name}" Command="{Binding ClickCommand}" IsEnabled="{Binding Enabled}">
<StackPanel Orientation="Horizontal">
<ContentPresenter Content="{Binding Icon}" />
<TextBlock
Padding="3 0"
IsVisible="{Binding Icon, Converter={x:Static ObjectConverters.IsNull}}"
Text="{Binding Name}"
/>
</StackPanel>
</Button>
</DataTemplate>
</ItemsPresenter.ItemTemplate>
</ItemsPresenter>
</UserControl>

View file

@ -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<List<object>> ItemsProperty = AvaloniaProperty.Register<ActionToolbar, List<object>>(nameof(Items));
private DispatcherTimer _timer;
public List<object> 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();
}
}
}
}
}

View file

@ -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<string> TextBindingProperty = AvaloniaProperty.Register<MesenTextEditor, string>(nameof(TextBinding), "");
public static readonly StyledProperty<string> TextBindingProperty = AvaloniaProperty.Register<MesenTextEditor, string>(nameof(TextBinding), "", defaultBindingMode: Avalonia.Data.BindingMode.TwoWay);
public string TextBinding
{
@ -36,14 +37,22 @@ namespace Mesen.Debugger.Controls
static MesenTextEditor()
{
TextBindingProperty.Changed.AddClassHandler<MesenTextEditor>((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<ICompletionData> 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);
}
}*/
}
}

View file

@ -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,
}
}

View file

@ -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;
}
}
}

View file

@ -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<DebuggerShortcutInfo> SharedShortcuts { get; set; } = new();
public List<DebuggerShortcutInfo> MemoryToolsShortcuts { get; set; } = new();
public List<DebuggerShortcutInfo> ScriptShortcuts { get; set; } = new();
public List<DebuggerShortcutInfo> 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
}
}

View file

@ -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)
},
};

View file

@ -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<object> FileMenuActions { get; private set; } = new();
public List<object> ScriptMenuActions { get; private set; } = new();
public List<object> HelpMenuActions { get; private set; } = new();
public List<object> 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<object> 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<object>();
}
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<bool> 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<bool> SaveScript()
{
if(!string.IsNullOrWhiteSpace(FilePath)) {
File.WriteAllText(FilePath, Code, Encoding.UTF8);
_originalText = Code;
return true;
} else {
return await SaveAs("NewScript.lua");
}
}
private async Task<bool> 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;
}
}
}
}

View file

@ -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);

View file

@ -32,25 +32,11 @@
<Style Selector="Button">
<Setter Property="MinWidth" Value="0" />
</Style>
<Style Selector=".IconBar Button">
<Setter Property="Padding" Value="0" />
</Style>
<Style Selector=".IconBar Button Image">
<Setter Property="Margin" Value="0" />
<Setter Property="Width" Value="16" />
<Setter Property="Height" Value="16" />
</Style>
<Style Selector="StackPanel Separator">
<Setter Property="Width" Value="2" />
<Setter Property="Height" Value="16" />
<Setter Property="Margin" Value="2 0" />
<Setter Property="Padding" Value="0" />
<Setter Property="Template">
<ControlTemplate>
<Rectangle Stroke="LightGray" StrokeThickness="1" Height="16" Width="1" />
</ControlTemplate>
</Setter>
</Style>
</Window.Styles>
<DockPanel>
@ -69,28 +55,8 @@
<Image Source="/Assets/Settings.png" />
</Button>
<StackPanel Classes="Toolbar" Orientation="Horizontal">
<ItemsPresenter Items="{CompiledBinding ToolbarItems}">
<ItemsPresenter.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsPresenter.ItemsPanel>
<ItemsPresenter.ItemTemplate>
<DataTemplate DataType="{x:Type du:ContextMenuAction}">
<Button ToolTip.Tip="{Binding Name}" Command="{Binding ClickCommand}" IsEnabled="{Binding Enabled}">
<StackPanel Orientation="Horizontal">
<ContentPresenter Content="{Binding Icon}" />
<TextBlock
Padding="3 0"
IsVisible="{Binding Icon, Converter={x:Static ObjectConverters.IsNull}}"
Text="{Binding Name}"
/>
</StackPanel>
</Button>
</DataTemplate>
</ItemsPresenter.ItemTemplate>
</ItemsPresenter>
<StackPanel Orientation="Horizontal">
<dc:ActionToolbar Items="{CompiledBinding ToolbarItems}" />
</StackPanel>
</DockPanel>
<DockPanel>

View file

@ -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();
}
}
}
}
}

View file

@ -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 @@
<vm:ScriptWindowViewModel />
</Design.DataContext>
<Window.Styles>
<Style Selector="Button">
<Setter Property="MinWidth" Value="0" />
</Style>
<Style Selector="Grid.main > Border">
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Margin" Value="1" />
</Style>
</Window.Styles>
<Grid Classes="main" ColumnDefinitions="*" RowDefinitions="Auto,*,100" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel Classes="Toolbar" Orientation="Horizontal">
<Button ToolTip.Tip="{l:Translate btnRun}" Click="OnRunClick">
<Image Source="/Assets/MediaPlay.png" />
</Button>
<Button ToolTip.Tip="{l:Translate btnStop}" Click="OnStopClick">
<Image Source="/Assets/MediaStop.png" />
</Button>
<Window.Resources>
<du:GridLengthConverter x:Key="GridLengthConverter" />
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="File" Classes="ActionMenu" Items="{CompiledBinding FileMenuActions}" />
<MenuItem Header="Script" Classes="ActionMenu" Items="{CompiledBinding ScriptMenuActions}" />
<MenuItem Header="Help" Classes="ActionMenu" Items="{CompiledBinding HelpMenuActions}" />
</Menu>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
<dc:ActionToolbar Items="{CompiledBinding ToolbarActions}" />
</StackPanel>
<Border Grid.Row="1">
<dc:MesenTextEditor
Name="Editor"
ShowLineNumbers="True"
FontFamily="{CompiledBinding Font.FontFamilyObject}"
FontSize="{CompiledBinding Font.FontSize}"
<Grid ColumnDefinitions="*" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="4" />
<RowDefinition MinHeight="50" Height="{CompiledBinding Config.LogWindowHeight, Mode=TwoWay, Converter={StaticResource GridLengthConverter}}" />
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderBrush="Gray" BorderThickness="1" Margin="1">
<dc:MesenTextEditor
Name="Editor"
ShowLineNumbers="True"
TextBinding="{CompiledBinding Code}"
FontFamily="{CompiledBinding Font.FontFamilyObject}"
FontSize="{CompiledBinding Font.FontSize}"
/>
</Border>
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" />
<TextBox
Grid.Row="2"
VerticalContentAlignment="Top"
Height="NaN"
Text="{CompiledBinding Log}"
IsReadOnly="True"
/>
</Border>
<TextBox Grid.Row="2" Height="NaN" VerticalContentAlignment="Top" />
</Grid>
</Grid>
</DockPanel>
</Window>

View file

@ -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<MesenTextEditor>("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);
}
}

View file

@ -1717,6 +1717,18 @@ x == [$150] || y == [10]
<Value ID="RunPpuFrame">Run one frame</Value>
<Value ID="BreakIn">Break in...</Value>
<Value ID="BreakOn">Break on...</Value>
<Value ID="RunScript">Run Script</Value>
<Value ID="StopScript">Stop Script</Value>
<Value ID="NewScript">New Script Window</Value>
<Value ID="Open">Open</Value>
<Value ID="Save">Save</Value>
<Value ID="SaveAs">Save as...</Value>
<Value ID="Exit">Exit</Value>
<Value ID="HelpApiReference">API Reference</Value>
<Value ID="RecentScripts">Recent Scripts</Value>
</Enum>
</Enums>
</Resources>

View file

@ -200,6 +200,9 @@
<Compile Update="Debugger\Controls\DebuggerKeyBindingButton.cs">
<DependentUpon>DebuggerKeyBindingButton</DependentUpon>
</Compile>
<Compile Update="Debugger\Controls\ActionToolbar.axaml.cs">
<DependentUpon>ActionToolbar.axaml</DependentUpon>
</Compile>
<Compile Update="Debugger\Controls\SpritePreviewPanel.axaml.cs">
<DependentUpon>SpritePreviewPanel.axaml</DependentUpon>
</Compile>

View file

@ -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<string?> OpenFile(string? initialFolder, IRenderRoot? parent, params string[] extensions)
{

View file

@ -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)