Mesen-X/GUI.NET/Config/DebuggerShortcutsConfig.cs

333 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Windows.Forms;
using Mesen.GUI.Forms;
using static Mesen.GUI.Forms.BaseForm;
namespace Mesen.GUI.Config
{
public class DebuggerShortcutsConfig
{
//Shared
[ShortcutName("Increase Font Size")]
public XmlKeys IncreaseFontSize = Keys.Control | Keys.Oemplus;
[ShortcutName("Decrease Font Size")]
public XmlKeys DecreaseFontSize = Keys.Control | Keys.OemMinus;
[ShortcutName("Reset Font Size")]
public XmlKeys ResetFontSize = Keys.Control | Keys.D0;
[ShortcutName("Go To...")]
public XmlKeys GoTo = Keys.Control | Keys.G;
[ShortcutName("Find")]
public XmlKeys Find = Keys.Control | Keys.F;
[ShortcutName("Find Next")]
public XmlKeys FindNext = Keys.F3;
[ShortcutName("Find Previous")]
public XmlKeys FindPrev = Keys.Shift | Keys.F3;
[ShortcutName("Undo")]
public XmlKeys Undo = Keys.Control | Keys.Z;
[ShortcutName("Copy")]
public XmlKeys Copy = Keys.Control | Keys.C;
[ShortcutName("Cut")]
public XmlKeys Cut = Keys.Control | Keys.X;
[ShortcutName("Paste")]
public XmlKeys Paste = Keys.Control | Keys.V;
[ShortcutName("Select All")]
public XmlKeys SelectAll = Keys.Control | Keys.A;
[ShortcutName("Refresh")]
public XmlKeys Refresh = Keys.F5;
[ShortcutName("Mark Selection as Code")]
public XmlKeys MarkAsCode = Keys.Control | Keys.D1;
[ShortcutName("Mark Selection as Data")]
public XmlKeys MarkAsData = Keys.Control | Keys.D2;
[ShortcutName("Mark Selection as Unidentified Code/Data")]
public XmlKeys MarkAsUnidentified = Keys.Control | Keys.D3;
[ShortcutName("Open APU Viewer")]
public XmlKeys OpenApuViewer = Keys.Control | Keys.U;
[ShortcutName("Open Assembler")]
public XmlKeys OpenAssembler = Keys.Control | Keys.K;
[ShortcutName("Open Debugger")]
public XmlKeys OpenDebugger = Keys.Control | Keys.D;
[ShortcutName("Open Event Viewer")]
public XmlKeys OpenEventViewer = Keys.Control | Keys.E;
[ShortcutName("Open Memory Tools")]
public XmlKeys OpenMemoryTools = Keys.Control | Keys.M;
[ShortcutName("Open PPU Viewer")]
public XmlKeys OpenPpuViewer = Keys.Control | Keys.P;
[ShortcutName("Open Script Window")]
public XmlKeys OpenScriptWindow = Keys.Control | Keys.N;
[ShortcutName("Open Trace Logger")]
public XmlKeys OpenTraceLogger = Keys.Control | Keys.J;
//Debugger window
[ShortcutName("Reset")]
public XmlKeys Reset = Keys.Control | Keys.R;
[ShortcutName("Power Cycle")]
public XmlKeys PowerCycle = Keys.Control | Keys.T;
[ShortcutName("Continue")]
public XmlKeys Continue = Keys.F5;
[ShortcutName("Break")]
public XmlKeys Break = Keys.Control | Keys.Alt | Keys.Cancel;
[ShortcutName("Toggle Break/Continue")]
public XmlKeys ToggleBreakContinue = Keys.Escape;
[ShortcutName("Step Into")]
public XmlKeys StepInto = Keys.F11;
[ShortcutName("Step Over")]
public XmlKeys StepOver = Keys.F10;
[ShortcutName("Step Out")]
public XmlKeys StepOut = Keys.Shift | Keys.F11;
[ShortcutName("Step Back")]
public XmlKeys StepBack = Keys.Shift | Keys.F10;
[ShortcutName("Run one PPU Cycle")]
public XmlKeys RunPpuCycle = Keys.F6;
[ShortcutName("Run one scanline")]
public XmlKeys RunPpuScanline = Keys.F7;
[ShortcutName("Run one frame")]
public XmlKeys RunPpuFrame = Keys.F8;
[ShortcutName("Break In...")]
public XmlKeys BreakIn = Keys.Control | Keys.B;
[ShortcutName("Break On...")]
public XmlKeys BreakOn = Keys.Alt | Keys.B;
[ShortcutName("Find Occurrences")]
public XmlKeys FindOccurrences = Keys.Control | Keys.Shift | Keys.F;
[ShortcutName("Go To Program Counter")]
public XmlKeys GoToProgramCounter = Keys.Alt | Keys.Multiply;
[ShortcutName("Toggle Verified Data Display")]
public XmlKeys ToggleVerifiedData = Keys.Alt | Keys.D1;
[ShortcutName("Toggle Unidentified Code/Data Display")]
public XmlKeys ToggleUnidentifiedCodeData = Keys.Alt | Keys.D2;
[ShortcutName("Code Window: Set Next Statement")]
public XmlKeys CodeWindow_SetNextStatement = Keys.Control | Keys.Shift | Keys.F10;
[ShortcutName("Code Window: Edit Subroutine")]
public XmlKeys CodeWindow_EditSubroutine = Keys.F4;
[ShortcutName("Code Window: Edit Selected Code")]
public XmlKeys CodeWindow_EditSelectedCode = Keys.None;
[ShortcutName("Code Window: Edit in Memory Viewer")]
public XmlKeys CodeWindow_EditInMemoryViewer = Keys.F1;
[ShortcutName("Code Window: Edit Label")]
public XmlKeys CodeWindow_EditLabel = Keys.F2;
[ShortcutName("Code Window: Navigate Back")]
public XmlKeys CodeWindow_NavigateBack = Keys.Alt | Keys.Left;
[ShortcutName("Code Window: Navigate Forward")]
public XmlKeys CodeWindow_NavigateForward = Keys.Alt | Keys.Right;
[ShortcutName("Code Window: Toggle Breakpoint")]
public XmlKeys CodeWindow_ToggleBreakpoint = Keys.F9;
[ShortcutName("Code Window: Disable/Enable Breakpoint")]
public XmlKeys CodeWindow_DisableEnableBreakpoint = Keys.Control | Keys.F9;
[ShortcutName("Code Window: Switch View (Disassembly / Source View)")]
public XmlKeys CodeWindow_SwitchView = Keys.Control | Keys.Q;
[ShortcutName("Function List: Edit Label")]
public XmlKeys FunctionList_EditLabel = Keys.F2;
[ShortcutName("Function List: Add Breakpoint")]
public XmlKeys FunctionList_AddBreakpoint = Keys.None;
[ShortcutName("Function List: Find Occurrences")]
public XmlKeys FunctionList_FindOccurrences = Keys.None;
[ShortcutName("Label List: Add Label")]
public XmlKeys LabelList_Add = Keys.Insert;
[ShortcutName("Label List: Edit Label")]
public XmlKeys LabelList_Edit = Keys.F2;
[ShortcutName("Label List: Delete Label")]
public XmlKeys LabelList_Delete = Keys.Delete;
[ShortcutName("Label List: Add Breakpoint")]
public XmlKeys LabelList_AddBreakpoint = Keys.None;
[ShortcutName("Label List: Add to Watch")]
public XmlKeys LabelList_AddToWatch = Keys.None;
[ShortcutName("Label List: Find Occurrences")]
public XmlKeys LabelList_FindOccurrences = Keys.None;
[ShortcutName("Breakpoint List: Add Breakpoint")]
public XmlKeys BreakpointList_Add = Keys.Insert;
[ShortcutName("Breakpoint List: Edit Breakpoint")]
public XmlKeys BreakpointList_Edit = Keys.F2;
[ShortcutName("Breakpoint List: Go To Location")]
public XmlKeys BreakpointList_GoToLocation = Keys.None;
[ShortcutName("Breakpoint List: Delete Breakpoint")]
public XmlKeys BreakpointList_Delete = Keys.Delete;
[ShortcutName("Watch List: Delete")]
public XmlKeys WatchList_Delete = Keys.Delete;
[ShortcutName("Save Rom")]
public XmlKeys SaveRom = Keys.Control | Keys.S;
[ShortcutName("Save Rom As...")]
public XmlKeys SaveRomAs = Keys.None;
[ShortcutName("Save edits as IPS patch...")]
public XmlKeys SaveEditAsIps = Keys.None;
[ShortcutName("Revert PRG/CHR changes")]
public XmlKeys RevertPrgChrChanges = Keys.None;
//Memory Tools
[ShortcutName("Freeze")]
public XmlKeys MemoryViewer_Freeze = Keys.Control | Keys.Q;
[ShortcutName("Unfreeze")]
public XmlKeys MemoryViewer_Unfreeze = Keys.Control | Keys.W;
[ShortcutName("Add to Watch")]
public XmlKeys MemoryViewer_AddToWatch = Keys.None;
[ShortcutName("Edit Breakpoint")]
public XmlKeys MemoryViewer_EditBreakpoint = Keys.None;
[ShortcutName("Edit Label")]
public XmlKeys MemoryViewer_EditLabel = Keys.None;
[ShortcutName("Import")]
public XmlKeys MemoryViewer_Import = Keys.Control | Keys.O;
[ShortcutName("Export")]
public XmlKeys MemoryViewer_Export = Keys.Control | Keys.S;
//Script Window
[ShortcutName("Open Script")]
public XmlKeys ScriptWindow_OpenScript = Keys.Control | Keys.N;
[ShortcutName("Save Script")]
public XmlKeys ScriptWindow_SaveScript = Keys.Control | Keys.S;
[ShortcutName("Run Script")]
public XmlKeys ScriptWindow_RunScript = Keys.F5;
[ShortcutName("Stop Script")]
public XmlKeys ScriptWindow_StopScript = Keys.Escape;
public static string GetShortcutDisplay(Keys keys)
{
if(keys == Keys.None) {
return "";
} else {
string keyString = new KeysConverter().ConvertToString(keys);
return keyString.Replace("+None", "").Replace("Oemplus", "+").Replace("Oemtilde", "Tilde").Replace("OemMinus", "-").Replace("Cancel", "Break").Replace("Escape", "Esc");
}
}
private static Dictionary<WeakReference<ToolStripMenuItem>, string> _bindings = new Dictionary<WeakReference<ToolStripMenuItem>, string>();
private static Dictionary<WeakReference<ToolStripMenuItem>, Control> _parents = new Dictionary<WeakReference<ToolStripMenuItem>, Control>();
public static void RegisterMenuItem(ToolStripMenuItem item, Control parent, string fieldName)
{
var weakRef = new WeakReference<ToolStripMenuItem>(item);
_bindings[weakRef] = fieldName;
_parents[weakRef] = parent;
//Remove old references
foreach(WeakReference<ToolStripMenuItem> itemRef in _bindings.Keys.ToArray()) {
ToolStripMenuItem menuItem;
if(!itemRef.TryGetTarget(out menuItem)) {
_bindings.Remove(itemRef);
_parents.Remove(itemRef);
}
}
}
public static void UpdateMenus()
{
foreach(WeakReference<ToolStripMenuItem> itemRef in _bindings.Keys) {
ToolStripMenuItem item;
if(itemRef.TryGetTarget(out item)) {
string fieldName = _bindings[itemRef];
Control parent = _parents[itemRef];
UpdateShortcutItem(item, parent, fieldName);
}
}
}
private static void ClearProcessCmdKeyHandler(ToolStripMenuItem item, Control parent)
{
Form parentForm = parent.FindForm();
if(parentForm is BaseForm) {
(parentForm as BaseForm).OnProcessCmdKey -= (ProcessCmdKeyHandler)item.Tag;
}
item.Tag = null;
}
public static void UpdateShortcutItem(ToolStripMenuItem item, Control parent, string fieldName)
{
if(item.Tag is ProcessCmdKeyHandler) {
ClearProcessCmdKeyHandler(item, parent);
}
Keys keys = (XmlKeys)typeof(DebuggerShortcutsConfig).GetField(fieldName).GetValue(ConfigManager.Config.DebugInfo.Shortcuts);
if((keys != Keys.None && !ToolStripManager.IsValidShortcut(keys)) || Program.IsMono) {
//Support normally invalid shortcut keys as a shortcut
item.ShortcutKeys = Keys.None;
item.ShortcutKeyDisplayString = GetShortcutDisplay(keys);
Form parentForm = parent.FindForm();
if(parentForm is BaseForm) {
ProcessCmdKeyHandler onProcessCmdKeyHandler = (Keys keyData) => {
if(parent.ContainsFocus && keyData == keys) {
item.PerformClick();
return true;
}
return false;
};
item.Tag = onProcessCmdKeyHandler;
(parentForm as BaseForm).OnProcessCmdKey += onProcessCmdKeyHandler;
}
} else {
item.ShortcutKeys = keys;
item.ShortcutKeyDisplayString = GetShortcutDisplay(keys);
}
}
}
public static class ToolStripMenuItemExtensions
{
public static void InitShortcut(this ToolStripMenuItem item, Control parent, string fieldName)
{
DebuggerShortcutsConfig.UpdateShortcutItem(item, parent, fieldName);
DebuggerShortcutsConfig.RegisterMenuItem(item, parent, fieldName);
}
}
public class XmlKeys
{
private Keys _keys = Keys.None;
public XmlKeys() { }
public XmlKeys(Keys k) { _keys = k; }
public static implicit operator Keys(XmlKeys k)
{
return k._keys;
}
public static implicit operator XmlKeys(Keys k)
{
return new XmlKeys(k);
}
[XmlAttribute]
public string Value
{
get { return _keys.ToString(); }
set
{
try {
Enum.TryParse<Keys>(value, out _keys);
} catch(Exception) {
_keys = Keys.None;
}
}
}
}
public class ShortcutNameAttribute : Attribute
{
public string Name { get; private set; }
public ShortcutNameAttribute(string name)
{
this.Name = name;
}
}
}