From 8d91557f4e9266c0feaa836057de1411d614c769 Mon Sep 17 00:00:00 2001 From: adelikat Date: Mon, 22 May 2017 12:51:34 -0500 Subject: [PATCH] cleanups in ToolManager --- BizHawk.Client.EmuHawk/tools/ToolManager.cs | 200 +++++++++++--------- 1 file changed, 106 insertions(+), 94 deletions(-) diff --git a/BizHawk.Client.EmuHawk/tools/ToolManager.cs b/BizHawk.Client.EmuHawk/tools/ToolManager.cs index c45a1dd6b0..12085bc660 100644 --- a/BizHawk.Client.EmuHawk/tools/ToolManager.cs +++ b/BizHawk.Client.EmuHawk/tools/ToolManager.cs @@ -5,20 +5,16 @@ using System.IO; using System.Linq; using System.Reflection; using System.ComponentModel; +using System.Windows.Forms; -using BizHawk.Emulation.Common.IEmulatorExtensions; using BizHawk.Client.Common; using BizHawk.Emulation.Common; using BizHawk.Common.ReflectionExtensions; -using System.Windows.Forms; - namespace BizHawk.Client.EmuHawk { public class ToolManager { - #region Fields - private readonly Form _owner; // TODO: merge ToolHelper code where logical @@ -26,12 +22,8 @@ namespace BizHawk.Client.EmuHawk // Also a UsesRam, and similar method private readonly List _tools = new List(); - #endregion - - #region cTor(s) - /// - /// Initialize an new ToolManager instance + /// Initializes a new instance of the class. /// /// Form that handle the ToolManager public ToolManager(Form owner) @@ -39,28 +31,24 @@ namespace BizHawk.Client.EmuHawk _owner = owner; } - #endregion - /// - /// Loads the tool dialog T (T must implemants ) , if it does not exist it will be created, if it is already open, it will be focused + /// Loads the tool dialog T (T must implements ) , if it does not exist it will be created, if it is already open, it will be focused /// This method should be used only if you can't use the generic one /// /// Type of tool you want to load /// Define if the tool form has to get the focus or not (Default is true) - /// An instanciated + /// An instantiated /// Raised if can't be casted into IToolForm internal IToolForm Load(Type toolType, bool focus = true) { if (!typeof(IToolForm).IsAssignableFrom(toolType)) { - throw new ArgumentException(string.Format("Type {0} does not implement IToolForm.", toolType.Name)); - } - else - { - //The type[] in parameter is used to avoid an ambigous name exception - MethodInfo method = GetType().GetMethod("Load", new Type[] { typeof(bool) }).MakeGenericMethod(toolType); - return (IToolForm)method.Invoke(this, new object[] { focus }); + throw new ArgumentException($"Type {toolType.Name} does not implement IToolForm."); } + + // The type[] in parameter is used to avoid an ambigous name exception + MethodInfo method = GetType().GetMethod("Load", new Type[] { typeof(bool) }).MakeGenericMethod(toolType); + return (IToolForm)method.Invoke(this, new object[] { focus }); } /// @@ -68,7 +56,7 @@ namespace BizHawk.Client.EmuHawk /// /// Type of tool you want to load /// Define if the tool form has to get the focus or not (Default is true) - /// An instanciated + /// An instantiated public T Load(bool focus = true) where T : class, IToolForm { @@ -79,9 +67,9 @@ namespace BizHawk.Client.EmuHawk /// Loads the tool dialog T (T must implement ) , if it does not exist it will be created, if it is already open, it will be focused /// /// Type of tool you want to load + /// Path to the .dll of the external tool /// Define if the tool form has to get the focus or not (Default is true) - /// Path to the dll of the external tool - /// An instanciated + /// An instantiated public T Load(string toolPath, bool focus = true) where T : class, IToolForm { @@ -95,11 +83,11 @@ namespace BizHawk.Client.EmuHawk T existingTool; if (isExternal) { - existingTool = (T)_tools.FirstOrDefault(x => x is T && x.GetType().Assembly.Location == toolPath); + existingTool = (T)_tools.FirstOrDefault(t => t is T && t.GetType().Assembly.Location == toolPath); } else { - existingTool = (T)_tools.FirstOrDefault(x => x is T); + existingTool = (T)_tools.FirstOrDefault(t => t is T); } if (existingTool != null) @@ -144,6 +132,7 @@ namespace BizHawk.Client.EmuHawk settings = new ToolDialogSettings(); Global.Config.CommonToolSettings[toolType] = settings; } + AttachSettingHooks(newTool as IToolFormAutoConfig, settings); } @@ -156,6 +145,7 @@ namespace BizHawk.Client.EmuHawk settings = new Dictionary(); Global.Config.CustomToolSettings[toolType] = settings; } + InstallCustomConfig(newTool, settings); } @@ -171,7 +161,7 @@ namespace BizHawk.Client.EmuHawk .Select(kvp => kvp.Key); var customSettings = Global.Config.CustomToolSettings - .Where(list => list.Value.Any(kvp => typeof(ToolDialogSettings).IsAssignableFrom(kvp.Value.GetType()) && (kvp.Value as ToolDialogSettings).AutoLoad)) + .Where(list => list.Value.Any(kvp => kvp.Value is ToolDialogSettings && ((ToolDialogSettings)kvp.Value).AutoLoad)) .Select(kvp => kvp.Key); var typeNames = genericSettings.Concat(customSettings); @@ -193,10 +183,10 @@ namespace BizHawk.Client.EmuHawk private static void RefreshSettings(Form form, ToolStripItemCollection menu, ToolDialogSettings settings, int idx) { - (menu[idx + 0] as ToolStripMenuItem).Checked = settings.SaveWindowPosition; - (menu[idx + 1] as ToolStripMenuItem).Checked = settings.TopMost; - (menu[idx + 2] as ToolStripMenuItem).Checked = settings.FloatingWindow; - (menu[idx + 3] as ToolStripMenuItem).Checked = settings.AutoLoad; + ((ToolStripMenuItem)menu[idx + 0]).Checked = settings.SaveWindowPosition; + ((ToolStripMenuItem)menu[idx + 1]).Checked = settings.TopMost; + ((ToolStripMenuItem)menu[idx + 2]).Checked = settings.FloatingWindow; + ((ToolStripMenuItem)menu[idx + 3]).Checked = settings.AutoLoad; form.TopMost = settings.TopMost; @@ -223,17 +213,22 @@ namespace BizHawk.Client.EmuHawk break; } } + if (dest == null) { var submenu = new ToolStripMenuItem("&Settings"); ms.Items.Add(submenu); dest = submenu.DropDownItems; } + break; } } + if (dest == null) + { throw new InvalidOperationException("IToolFormAutoConfig must have menu to bind to!"); + } int idx = dest.Count; @@ -250,10 +245,13 @@ namespace BizHawk.Client.EmuHawk form.StartPosition = FormStartPosition.Manual; form.Location = settings.WindowPosition; } + if (settings.UseWindowSize) { if (form.FormBorderStyle == FormBorderStyle.Sizable || form.FormBorderStyle == FormBorderStyle.SizableToolWindow) + { form.Size = settings.WindowSize; + } } form.FormClosing += (o, e) => @@ -262,8 +260,16 @@ namespace BizHawk.Client.EmuHawk { settings.Wndx = form.Location.X; settings.Wndy = form.Location.Y; - if (settings.Wndx < 0) settings.Wndx = 0; - if (settings.Wndy < 0) settings.Wndy = 0; + if (settings.Wndx < 0) + { + settings.Wndx = 0; + } + + if (settings.Wndy < 0) + { + settings.Wndy = 0; + } + settings.Width = form.Right - form.Left; // why not form.Size.Width? settings.Height = form.Bottom - form.Top; } @@ -271,29 +277,29 @@ namespace BizHawk.Client.EmuHawk dest[idx + 0].Click += (o, e) => { - bool val = !(o as ToolStripMenuItem).Checked; + bool val = !((ToolStripMenuItem)o).Checked; settings.SaveWindowPosition = val; - (o as ToolStripMenuItem).Checked = val; + ((ToolStripMenuItem)o).Checked = val; }; dest[idx + 1].Click += (o, e) => { - bool val = !(o as ToolStripMenuItem).Checked; + bool val = !((ToolStripMenuItem)o).Checked; settings.TopMost = val; - (o as ToolStripMenuItem).Checked = val; + ((ToolStripMenuItem)o).Checked = val; form.TopMost = val; }; dest[idx + 2].Click += (o, e) => { - bool val = !(o as ToolStripMenuItem).Checked; + bool val = !((ToolStripMenuItem)o).Checked; settings.FloatingWindow = val; - (o as ToolStripMenuItem).Checked = val; + ((ToolStripMenuItem)o).Checked = val; form.Owner = val ? null : _owner; }; dest[idx + 3].Click += (o, e) => { - bool val = !(o as ToolStripMenuItem).Checked; + bool val = !((ToolStripMenuItem)o).Checked; settings.AutoLoad = val; - (o as ToolStripMenuItem).Checked = val; + ((ToolStripMenuItem)o).Checked = val; }; dest[idx + 4].Click += (o, e) => { @@ -313,7 +319,9 @@ namespace BizHawk.Client.EmuHawk Type type = tool.GetType(); var props = type.GetPropertiesWithAttrib(typeof(ConfigPersistAttribute)).ToList(); if (props.Count == 0) + { return; + } foreach (var prop in props) { @@ -329,18 +337,19 @@ namespace BizHawk.Client.EmuHawk // back on regular object serialization when needed. so try to undo a TypeConverter // operation here var converter = TypeDescriptor.GetConverter(prop.PropertyType); - val = converter.ConvertFromString(null,System.Globalization.CultureInfo.InvariantCulture,((string)val)); + val = converter.ConvertFromString(null, System.Globalization.CultureInfo.InvariantCulture, (string)val); } else if (!(val is bool) && prop.PropertyType.IsPrimitive) { // numeric constanst are similarly hosed val = Convert.ChangeType(val, prop.PropertyType, System.Globalization.CultureInfo.InvariantCulture); } + prop.SetValue(tool, val, null); } } - (tool as Form).FormClosing += (o, e) => SaveCustomConfig(tool, data, props); + ((Form)tool).FormClosing += (o, e) => SaveCustomConfig(tool, data, props); } private static void SaveCustomConfig(IToolForm tool, Dictionary data, List props) @@ -352,13 +361,13 @@ namespace BizHawk.Client.EmuHawk } } - /// /// Determines whether a given IToolForm is already loaded /// + /// Type of tool to check public bool IsLoaded() where T : IToolForm { - var existingTool = _tools.FirstOrDefault(x => x is T); + var existingTool = _tools.FirstOrDefault(t => t is T); if (existingTool != null) { return !existingTool.IsDisposed; @@ -376,14 +385,16 @@ namespace BizHawk.Client.EmuHawk /// /// Returns true if an instance of T exists /// + /// Type of tool to check public bool Has() where T : IToolForm { - return _tools.Any(x => x is T && !x.IsDisposed); + return _tools.Any(t => t is T && !t.IsDisposed); } /// /// Gets the instance of T, or creates and returns a new instance /// + /// Type of tool to get public IToolForm Get() where T : class, IToolForm { return Load(false); @@ -393,53 +404,58 @@ namespace BizHawk.Client.EmuHawk { get { - //return _tools.Where(t => !t.IsDisposed); return Assembly .GetAssembly(typeof(IToolForm)) .GetTypes() .Where(t => typeof(IToolForm).IsAssignableFrom(t)) .Where(t => !t.IsInterface) - .Where(t => IsAvailable(t)); + .Where(IsAvailable); } } public void UpdateBefore() { - var beforeList = _tools.Where(x => x.UpdateBefore); + var beforeList = _tools.Where(t => t.UpdateBefore); foreach (var tool in beforeList) { - if (!tool.IsDisposed || - (tool is RamWatch && Global.Config.DisplayRamWatch)) // RAM Watch hack, on screen display should run even if RAM Watch is closed + if (!tool.IsDisposed + || (tool is RamWatch && Global.Config.DisplayRamWatch)) // RAM Watch hack, on screen display should run even if RAM Watch is closed { tool.UpdateValues(); } } + foreach (var tool in _tools) + { tool.NewUpdate(ToolFormUpdateType.PreFrame); + } } public void UpdateAfter() { - var afterList = _tools.Where(x => !x.UpdateBefore); + var afterList = _tools.Where(t => !t.UpdateBefore); foreach (var tool in afterList) { - if (!tool.IsDisposed || - (tool is RamWatch && Global.Config.DisplayRamWatch)) // RAM Watch hack, on screen display should run even if RAM Watch is closed + if (!tool.IsDisposed + || (tool is RamWatch && Global.Config.DisplayRamWatch)) // RAM Watch hack, on screen display should run even if RAM Watch is closed { tool.UpdateValues(); } } foreach (var tool in _tools) + { tool.NewUpdate(ToolFormUpdateType.PostFrame); + } } /// /// Calls UpdateValues() on an instance of T, if it exists /// + /// Type of tool to update public void UpdateValues() where T : IToolForm { - var tool = _tools.FirstOrDefault(x => x is T); + var tool = _tools.FirstOrDefault(t => t is T); if (tool != null) { if (!tool.IsDisposed || @@ -488,13 +504,11 @@ namespace BizHawk.Client.EmuHawk /// /// Calls Restart() on an instance of T, if it exists /// + /// Type of tool to restart public void Restart() where T : IToolForm { - var tool = _tools.FirstOrDefault(x => x is T); - if (tool != null) - { - tool.Restart(); - } + var tool = _tools.FirstOrDefault(t => t is T); + tool?.Restart(); } /// @@ -516,6 +530,7 @@ namespace BizHawk.Client.EmuHawk /// Calls AskSave() on an instance of T, if it exists, else returns true /// The caller should interpret false as cancel and will back out of the action that invokes this call /// + /// Type of tool public bool AskSave() where T : IToolForm { if (Global.Config.SupressAskSave) // User has elected to not be nagged @@ -523,23 +538,22 @@ namespace BizHawk.Client.EmuHawk return true; } - var tool = _tools.FirstOrDefault(x => x is T); + var tool = _tools.FirstOrDefault(t => t is T); if (tool != null) { return tool.AskSaveChanges(); } - else - { - return false; - } + + return false; } /// /// If T exists, this call will close the tool, and remove it from memory /// + /// Type of tool to close public void Close() where T : IToolForm { - var tool = _tools.FirstOrDefault(x => x is T); + var tool = _tools.FirstOrDefault(t => t is T); if (tool != null) { tool.Close(); @@ -549,7 +563,7 @@ namespace BizHawk.Client.EmuHawk public void Close(Type toolType) { - var tool = _tools.FirstOrDefault(x => toolType.IsAssignableFrom(x.GetType())); + var tool = _tools.FirstOrDefault(toolType.IsInstanceOfType); if (tool != null) { @@ -560,7 +574,7 @@ namespace BizHawk.Client.EmuHawk public void Close() { - _tools.ForEach(x => x.Close()); + _tools.ForEach(t => t.Close()); _tools.Clear(); } @@ -568,7 +582,7 @@ namespace BizHawk.Client.EmuHawk /// Create a new instance of an IToolForm and return it /// /// Type of tool you want to create - /// Path dll for an external tool + /// Path .dll for an external tool /// New instance of an IToolForm private IToolForm CreateInstance(string dllPath) where T : IToolForm @@ -586,13 +600,14 @@ namespace BizHawk.Client.EmuHawk { IToolForm tool; - //Specific case for custom tools - //TODO: Use AppDomain in order to be able to unload the assembly - //Hard stuff as we need a proxy object that inherit from MarshalByRefObject. + // Specific case for custom tools + // TODO: Use AppDomain in order to be able to unload the assembly + // Hard stuff as we need a proxy object that inherit from MarshalByRefObject. if (toolType == typeof(IExternalToolForm)) { - if (MessageBox.Show("Are you sure want to load this external tool?\r\nAccept ONLY if you trust the source and if you know what you're doing. In any other case, choose no." - , "Confirmm loading", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) + if (MessageBox.Show( + "Are you sure want to load this external tool?\r\nAccept ONLY if you trust the source and if you know what you're doing. In any other case, choose no.", + "Confirmm loading", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { try { @@ -662,11 +677,11 @@ namespace BizHawk.Client.EmuHawk public void FastUpdateBefore() { - var beforeList = _tools.Where(x => x.UpdateBefore); + var beforeList = _tools.Where(t => t.UpdateBefore); foreach (var tool in beforeList) { - if (!tool.IsDisposed || - (tool is RamWatch && Global.Config.DisplayRamWatch)) // RAM Watch hack, on screen display should run even if RAM Watch is closed + if (!tool.IsDisposed + || (tool is RamWatch && Global.Config.DisplayRamWatch)) // RAM Watch hack, on screen display should run even if RAM Watch is closed { tool.FastUpdate(); } @@ -680,11 +695,11 @@ namespace BizHawk.Client.EmuHawk LuaConsole.ResumeScripts(true); } - var afterList = _tools.Where(x => !x.UpdateBefore); + var afterList = _tools.Where(t => !t.UpdateBefore); foreach (var tool in afterList) { - if (!tool.IsDisposed || - (tool is RamWatch && Global.Config.DisplayRamWatch)) // RAM Watch hack, on screen display should run even if RAM Watch is closed + if (!tool.IsDisposed + || (tool is RamWatch && Global.Config.DisplayRamWatch)) // RAM Watch hack, on screen display should run even if RAM Watch is closed { tool.FastUpdate(); } @@ -722,13 +737,8 @@ namespace BizHawk.Client.EmuHawk .OfType() .FirstOrDefault(); - if (attr == null) // If no attributes there is no supported systems documented so assume all - { - return true; - } - // If no supported systems mentioned assume all - if (attr.SupportedSystems != null && attr.SupportedSystems.Any()) + if (attr?.SupportedSystems != null && attr.SupportedSystems.Any()) { return attr.SupportedSystems.Contains(Global.Emulator.SystemId); } @@ -743,7 +753,7 @@ namespace BizHawk.Client.EmuHawk { get { - var tool = _tools.FirstOrDefault(x => x is RamWatch); + var tool = _tools.FirstOrDefault(t => t is RamWatch); if (tool != null) { if (tool.IsDisposed) @@ -766,7 +776,7 @@ namespace BizHawk.Client.EmuHawk { get { - var tool = _tools.FirstOrDefault(x => x is RamSearch); + var tool = _tools.FirstOrDefault(t => t is RamSearch); if (tool != null) { if (tool.IsDisposed) @@ -789,7 +799,7 @@ namespace BizHawk.Client.EmuHawk { get { - var tool = _tools.FirstOrDefault(x => x is Cheats); + var tool = _tools.FirstOrDefault(t => t is Cheats); if (tool != null) { if (tool.IsDisposed) @@ -812,7 +822,7 @@ namespace BizHawk.Client.EmuHawk { get { - var tool = _tools.FirstOrDefault(x => x is HexEditor); + var tool = _tools.FirstOrDefault(t => t is HexEditor); if (tool != null) { if (tool.IsDisposed) @@ -835,7 +845,7 @@ namespace BizHawk.Client.EmuHawk { get { - var tool = _tools.FirstOrDefault(x => x is VirtualpadTool); + var tool = _tools.FirstOrDefault(t => t is VirtualpadTool); if (tool != null) { if (tool.IsDisposed) @@ -858,7 +868,7 @@ namespace BizHawk.Client.EmuHawk { get { - var tool = _tools.FirstOrDefault(x => x is SNESGraphicsDebugger); + var tool = _tools.FirstOrDefault(t => t is SNESGraphicsDebugger); if (tool != null) { if (tool.IsDisposed) @@ -881,7 +891,7 @@ namespace BizHawk.Client.EmuHawk { get { - var tool = _tools.FirstOrDefault(x => x is LuaConsole); + var tool = _tools.FirstOrDefault(t => t is LuaConsole); if (tool != null) { if (tool.IsDisposed) @@ -906,9 +916,11 @@ namespace BizHawk.Client.EmuHawk { // prevent nasty silent corruption if (!GlobalWin.Tools.IsLoaded()) + { System.Diagnostics.Debug.Fail("TAStudio does not exist!"); + } - var tool = _tools.FirstOrDefault(x => x is TAStudio); + var tool = _tools.FirstOrDefault(t => t is TAStudio); if (tool != null) { if (tool.IsDisposed)