Browse Source

Move Settings to ILSpyX (#2869)

* Move ILSpySettings to ILSpyX
* Make settings file path configurable using a static provider interface
* Move MiscSettings to ILSpyX, rename existing to MiscSettingsVieModel
* Introduce static Load for DecompilerSettings on interface
* Add path provider for ilspycmd parameter scenario
* Allow for saving of MiscSettingsPanel
* Rename DisplaySettings to DisplaySettingsViewModel
* Add SaveDecompilerSettings
pull/2871/head
Christoph Wille 2 years ago committed by GitHub
parent
commit
003a2b45b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      ICSharpCode.ILSpyX/AssemblyListManager.cs
  2. 40
      ICSharpCode.ILSpyX/Settings/DefaultSettingsFilePathProvider.cs
  3. 31
      ICSharpCode.ILSpyX/Settings/ILSpySettings.cs
  4. 42
      ICSharpCode.ILSpyX/Settings/IMiscSettings.cs
  5. 27
      ICSharpCode.ILSpyX/Settings/ISettingsFilePathProvider.cs
  6. 69
      ICSharpCode.ILSpyX/Settings/ISettingsProvider.cs
  7. 32
      ICSharpCode.ILSpyX/Settings/ISettingsSection.cs
  8. 43
      ICSharpCode.ILSpyX/Settings/MiscSettings.cs
  9. 1
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
  10. 1
      ILSpy.ReadyToRun/ReadyToRunOptions.cs
  11. 1
      ILSpy/AboutPage.cs
  12. 3
      ILSpy/App.xaml.cs
  13. 1
      ILSpy/Commands/CheckForUpdatesCommand.cs
  14. 4
      ILSpy/DecompilationOptions.cs
  15. 38
      ILSpy/ILSpySettingsFilePathProvider.cs
  16. 3
      ILSpy/MainWindow.xaml.cs
  17. 27
      ILSpy/Options/DecompilerSettingsPanel.xaml.cs
  18. 2
      ILSpy/Options/DisplaySettingsPanel.xaml
  19. 10
      ILSpy/Options/DisplaySettingsPanel.xaml.cs
  20. 6
      ILSpy/Options/DisplaySettingsViewModel.cs
  21. 31
      ILSpy/Options/MiscSettingsPanel.xaml.cs
  22. 9
      ILSpy/Options/MiscSettingsViewModel.cs
  23. 1
      ILSpy/Options/OptionsDialog.xaml.cs
  24. 1
      ILSpy/SessionSettings.cs
  25. 4
      ILSpy/TextView/DecompilerTextView.cs
  26. 2
      ILSpy/Themes/WindowStyleManagerBehavior.cs
  27. 1
      TestPlugin/CustomOptionPage.xaml.cs

9
ICSharpCode.ILSpyX/AssemblyListManager.cs

@ -23,17 +23,10 @@ using System.Linq;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpyX namespace ICSharpCode.ILSpyX
{ {
public interface ISettingsProvider
{
XElement this[XName section] { get; }
void Update(Action<XElement> action);
ISettingsProvider Load();
}
/// <summary> /// <summary>
/// Manages the available assembly lists. /// Manages the available assembly lists.
/// ///

40
ICSharpCode.ILSpyX/Settings/DefaultSettingsFilePathProvider.cs

@ -0,0 +1,40 @@
// Copyright (c) 2022 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpyX.Settings
{
/// <summary>
/// Used in scenarios where the user passes a path and that is to be used, eg ilspycmd parameter
/// </summary>
public class DefaultSettingsFilePathProvider : ISettingsFilePathProvider
{
private readonly string _providedPath;
public DefaultSettingsFilePathProvider(string providedPath)
{
_providedPath = providedPath;
}
public string GetSettingsFilePath()
{
return _providedPath;
}
}
}

31
ILSpy/ILSpySettings.cs → ICSharpCode.ILSpyX/Settings/ILSpySettings.cs

@ -22,15 +22,18 @@ using System.Threading;
using System.Xml; using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpyX.Settings
namespace ICSharpCode.ILSpy
{ {
/// <summary> /// <summary>
/// Manages IL Spy settings. /// Manages IL Spy settings.
/// </summary> /// </summary>
public class ILSpySettings : ISettingsProvider public class ILSpySettings : ISettingsProvider
{ {
/// <summary>
/// This settings file path provider determines where to load settings file from, includes filename
/// </summary>
public static ISettingsFilePathProvider? SettingsFilePathProvider { get; set; }
readonly XElement root; readonly XElement root;
ILSpySettings() ILSpySettings()
@ -62,6 +65,11 @@ namespace ICSharpCode.ILSpy
try try
{ {
XDocument doc = LoadWithoutCheckingCharacters(GetConfigFile()); XDocument doc = LoadWithoutCheckingCharacters(GetConfigFile());
if (null == doc.Root)
{
return new ILSpySettings();
}
return new ILSpySettings(doc.Root); return new ILSpySettings(doc.Root);
} }
catch (IOException) catch (IOException)
@ -87,7 +95,7 @@ namespace ICSharpCode.ILSpy
{ {
Update( Update(
delegate (XElement root) { delegate (XElement root) {
XElement existingElement = root.Element(section.Name); XElement? existingElement = root.Element(section.Name);
if (existingElement != null) if (existingElement != null)
existingElement.ReplaceWith(section); existingElement.ReplaceWith(section);
else else
@ -113,14 +121,14 @@ namespace ICSharpCode.ILSpy
catch (IOException) catch (IOException)
{ {
// ensure the directory exists // ensure the directory exists
Directory.CreateDirectory(Path.GetDirectoryName(config)); Directory.CreateDirectory(Path.GetDirectoryName(config)!);
doc = new XDocument(new XElement("ILSpy")); doc = new XDocument(new XElement("ILSpy"));
} }
catch (XmlException) catch (XmlException)
{ {
doc = new XDocument(new XElement("ILSpy")); doc = new XDocument(new XElement("ILSpy"));
} }
doc.Root.SetAttributeValue("version", DecompilerVersionInfo.Major + "." + DecompilerVersionInfo.Minor + "." + DecompilerVersionInfo.Build + "." + DecompilerVersionInfo.Revision); doc.Root!.SetAttributeValue("version", DecompilerVersionInfo.Major + "." + DecompilerVersionInfo.Minor + "." + DecompilerVersionInfo.Build + "." + DecompilerVersionInfo.Revision);
action(doc.Root); action(doc.Root);
doc.Save(config, SaveOptions.None); doc.Save(config, SaveOptions.None);
} }
@ -133,12 +141,11 @@ namespace ICSharpCode.ILSpy
static string GetConfigFile() static string GetConfigFile()
{ {
if (App.CommandLineArguments.ConfigFile != null) if (null != SettingsFilePathProvider)
return App.CommandLineArguments.ConfigFile; return SettingsFilePathProvider.GetSettingsFilePath();
string localPath = Path.Combine(Path.GetDirectoryName(typeof(MainWindow).Assembly.Location), "ILSpy.xml");
if (File.Exists(localPath)) throw new ArgumentNullException(nameof(SettingsFilePathProvider));
return localPath; // return "ILSpy.xml";
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ICSharpCode\\ILSpy.xml");
} }
ISettingsProvider ISettingsProvider.Load() ISettingsProvider ISettingsProvider.Load()

42
ICSharpCode.ILSpyX/Settings/IMiscSettings.cs

@ -0,0 +1,42 @@
// Copyright (c) 2022 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Xml.Linq;
namespace ICSharpCode.ILSpyX.Settings
{
public interface IMiscSettings
{
public bool AllowMultipleInstances { get; set; }
public bool LoadPreviousAssemblies { get; set; }
public static void Save(XElement root, IMiscSettings miscSettings)
{
var section = new XElement("MiscSettings");
section.SetAttributeValue(nameof(miscSettings.AllowMultipleInstances), miscSettings.AllowMultipleInstances);
section.SetAttributeValue(nameof(miscSettings.LoadPreviousAssemblies), miscSettings.LoadPreviousAssemblies);
XElement? existingElement = root.Element("MiscSettings");
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
}
}
}

27
ICSharpCode.ILSpyX/Settings/ISettingsFilePathProvider.cs

@ -0,0 +1,27 @@
// Copyright (c) 2022 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpyX.Settings
{
public interface ISettingsFilePathProvider
{
string GetSettingsFilePath();
}
}

69
ICSharpCode.ILSpyX/Settings/ISettingsProvider.cs

@ -0,0 +1,69 @@
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using static System.Collections.Specialized.BitVector32;
namespace ICSharpCode.ILSpyX.Settings
{
public interface ISettingsProvider
{
XElement this[XName section] { get; }
void Update(Action<XElement> action);
ISettingsProvider Load();
public static ICSharpCode.Decompiler.DecompilerSettings LoadDecompilerSettings(ISettingsProvider settingsProvider)
{
XElement e = settingsProvider["DecompilerSettings"];
var newSettings = new Decompiler.DecompilerSettings();
var properties = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
foreach (var p in properties)
{
var value = (bool?)e.Attribute(p.Name);
if (value.HasValue)
p.SetValue(newSettings, value.Value);
}
return newSettings;
}
public static void SaveDecompilerSettings(XElement root, ICSharpCode.Decompiler.DecompilerSettings newSettings)
{
var properties = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
XElement section = new XElement("DecompilerSettings");
foreach (var p in properties)
{
section.SetAttributeValue(p.Name, p.GetValue(newSettings));
}
XElement? existingElement = root.Element("DecompilerSettings");
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
}
}
}

32
ICSharpCode.ILSpyX/Settings/ISettingsSection.cs

@ -0,0 +1,32 @@
// Copyright (c) 2022 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpyX.Settings
{
public interface ISettingsSection<TSelf>
{
// This should be abstract, but that needs C# 11.0 (see IParseable<TSelf>)
// Keep it to be enabled in the future
public static TSelf Load(ISettingsProvider settingsProvider)
{
throw new NotImplementedException();
}
}
}

43
ICSharpCode.ILSpyX/Settings/MiscSettings.cs

@ -0,0 +1,43 @@
// Copyright (c) 2022 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Xml.Linq;
namespace ICSharpCode.ILSpyX.Settings
{
public class MiscSettings : IMiscSettings, ISettingsSection<MiscSettings>
{
private MiscSettings()
{
}
public bool AllowMultipleInstances { get; set; }
public bool LoadPreviousAssemblies { get; set; }
public static MiscSettings Load(ISettingsProvider settingsProvider)
{
XElement e = settingsProvider["MiscSettings"];
var s = new MiscSettings();
s.AllowMultipleInstances = (bool?)e.Attribute(nameof(s.AllowMultipleInstances)) ?? false;
s.LoadPreviousAssemblies = (bool?)e.Attribute(nameof(s.LoadPreviousAssemblies)) ?? true;
return s;
}
}
}

1
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs

@ -21,6 +21,7 @@ using System.Windows.Controls;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.ReadyToRun namespace ICSharpCode.ILSpy.ReadyToRun
{ {

1
ILSpy.ReadyToRun/ReadyToRunOptions.cs

@ -19,6 +19,7 @@
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.ReadyToRun namespace ICSharpCode.ILSpy.ReadyToRun
{ {

1
ILSpy/AboutPage.cs

@ -35,6 +35,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Themes; using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {

3
ILSpy/App.xaml.cs

@ -32,6 +32,7 @@ using System.Windows.Navigation;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpyX.Settings;
using Microsoft.VisualStudio.Composition; using Microsoft.VisualStudio.Composition;
@ -59,6 +60,8 @@ namespace ICSharpCode.ILSpy
public App() public App()
{ {
ILSpySettings.SettingsFilePathProvider = new ILSpySettingsFilePathProvider();
var cmdArgs = Environment.GetCommandLineArgs().Skip(1); var cmdArgs = Environment.GetCommandLineArgs().Skip(1);
App.CommandLineArguments = new CommandLineArguments(cmdArgs); App.CommandLineArguments = new CommandLineArguments(cmdArgs);
bool forceSingleInstance = (App.CommandLineArguments.SingleInstance ?? true) bool forceSingleInstance = (App.CommandLineArguments.SingleInstance ?? true)

1
ILSpy/Commands/CheckForUpdatesCommand.cs

@ -18,6 +18,7 @@
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {

4
ILSpy/DecompilationOptions.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy
internal int StepLimit = int.MaxValue; internal int StepLimit = int.MaxValue;
internal bool IsDebug = false; internal bool IsDebug = false;
public DecompilationOptions(LanguageVersion version, Decompiler.DecompilerSettings settings, DisplaySettings displaySettings) public DecompilationOptions(LanguageVersion version, Decompiler.DecompilerSettings settings, DisplaySettingsViewModel displaySettings)
{ {
if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion)) if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion))
languageVersion = Decompiler.CSharp.LanguageVersion.Latest; languageVersion = Decompiler.CSharp.LanguageVersion.Latest;
@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy
newSettings.CSharpFormattingOptions.IndentationString = GetIndentationString(displaySettings); newSettings.CSharpFormattingOptions.IndentationString = GetIndentationString(displaySettings);
} }
private string GetIndentationString(DisplaySettings displaySettings) private string GetIndentationString(DisplaySettingsViewModel displaySettings)
{ {
if (displaySettings.IndentationUseTabs) if (displaySettings.IndentationUseTabs)
{ {

38
ILSpy/ILSpySettingsFilePathProvider.cs

@ -0,0 +1,38 @@
// Copyright (c) 2022 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy
{
internal class ILSpySettingsFilePathProvider : ISettingsFilePathProvider
{
public string GetSettingsFilePath()
{
if (App.CommandLineArguments.ConfigFile != null)
return App.CommandLineArguments.ConfigFile;
string localPath = Path.Combine(Path.GetDirectoryName(typeof(MainWindow).Assembly.Location), "ILSpy.xml");
if (File.Exists(localPath))
return localPath;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ICSharpCode\\ILSpy.xml");
}
}
}

3
ILSpy/MainWindow.xaml.cs

@ -52,6 +52,7 @@ using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels; using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX; using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Settings;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Microsoft.Win32; using Microsoft.Win32;
@ -103,7 +104,7 @@ namespace ICSharpCode.ILSpy
public DecompilerSettings CurrentDecompilerSettings { get; internal set; } public DecompilerSettings CurrentDecompilerSettings { get; internal set; }
public DisplaySettings CurrentDisplaySettings { get; internal set; } public DisplaySettingsViewModel CurrentDisplaySettings { get; internal set; }
public DecompilationOptions CreateDecompilationOptions() public DecompilationOptions CreateDecompilationOptions()
{ {

27
ILSpy/Options/DecompilerSettingsPanel.xaml.cs

@ -24,6 +24,8 @@ using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.Options namespace ICSharpCode.ILSpy.Options
{ {
/// <summary> /// <summary>
@ -39,17 +41,7 @@ namespace ICSharpCode.ILSpy.Options
public static Decompiler.DecompilerSettings LoadDecompilerSettings(ILSpySettings settings) public static Decompiler.DecompilerSettings LoadDecompilerSettings(ILSpySettings settings)
{ {
XElement e = settings["DecompilerSettings"]; return ISettingsProvider.LoadDecompilerSettings(settings);
var newSettings = new Decompiler.DecompilerSettings();
var properties = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
foreach (var p in properties)
{
var value = (bool?)e.Attribute(p.Name);
if (value.HasValue)
p.SetValue(newSettings, value.Value);
}
return newSettings;
} }
public void Load(ILSpySettings settings) public void Load(ILSpySettings settings)
@ -59,19 +51,8 @@ namespace ICSharpCode.ILSpy.Options
public void Save(XElement root) public void Save(XElement root)
{ {
XElement section = new XElement("DecompilerSettings");
var newSettings = ((DecompilerSettingsViewModel)this.DataContext).ToDecompilerSettings(); var newSettings = ((DecompilerSettingsViewModel)this.DataContext).ToDecompilerSettings();
var properties = typeof(Decompiler.DecompilerSettings).GetProperties() ISettingsProvider.SaveDecompilerSettings(root, newSettings);
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
foreach (var p in properties)
{
section.SetAttributeValue(p.Name, p.GetValue(newSettings));
}
XElement existingElement = root.Element("DecompilerSettings");
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
MainWindow.Instance.CurrentDecompilerSettings = newSettings; MainWindow.Instance.CurrentDecompilerSettings = newSettings;
MainWindow.Instance.AssemblyListManager.ApplyWinRTProjections = newSettings.ApplyWindowsRuntimeProjections; MainWindow.Instance.AssemblyListManager.ApplyWinRTProjections = newSettings.ApplyWindowsRuntimeProjections;

2
ILSpy/Options/DisplaySettingsPanel.xaml

@ -6,7 +6,7 @@
xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DataContext="{d:DesignInstance local:DisplaySettings}"> d:DataContext="{d:DesignInstance local:DisplaySettingsViewModel}">
<UserControl.Resources> <UserControl.Resources>
<local:FontSizeConverter x:Key="fontSizeConv" /> <local:FontSizeConverter x:Key="fontSizeConv" />
</UserControl.Resources> </UserControl.Resources>

10
ILSpy/Options/DisplaySettingsPanel.xaml.cs

@ -26,6 +26,8 @@ using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.Options namespace ICSharpCode.ILSpy.Options
{ {
/// <summary> /// <summary>
@ -94,10 +96,10 @@ namespace ICSharpCode.ILSpy.Options
select ff).ToArray(); select ff).ToArray();
} }
public static DisplaySettings LoadDisplaySettings(ILSpySettings settings) public static DisplaySettingsViewModel LoadDisplaySettings(ILSpySettings settings)
{ {
XElement e = settings["DisplaySettings"]; XElement e = settings["DisplaySettings"];
var s = new DisplaySettings(); var s = new DisplaySettingsViewModel();
s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas"); s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas");
s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3; s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3;
s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false; s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false;
@ -124,7 +126,7 @@ namespace ICSharpCode.ILSpy.Options
public void Save(XElement root) public void Save(XElement root)
{ {
var s = (DisplaySettings)this.DataContext; var s = (DisplaySettingsViewModel)this.DataContext;
var section = new XElement("DisplaySettings"); var section = new XElement("DisplaySettings");
section.SetAttributeValue("Font", s.SelectedFont.Source); section.SetAttributeValue("Font", s.SelectedFont.Source);
@ -174,7 +176,7 @@ namespace ICSharpCode.ILSpy.Options
public void LoadDefaults() public void LoadDefaults()
{ {
MainWindow.Instance.CurrentDisplaySettings.CopyValues(new DisplaySettings()); MainWindow.Instance.CurrentDisplaySettings.CopyValues(new DisplaySettingsViewModel());
this.DataContext = MainWindow.Instance.CurrentDisplaySettings; this.DataContext = MainWindow.Instance.CurrentDisplaySettings;
} }
} }

6
ILSpy/Options/DisplaySettings.cs → ILSpy/Options/DisplaySettingsViewModel.cs

@ -25,9 +25,9 @@ namespace ICSharpCode.ILSpy.Options
/// <summary> /// <summary>
/// Description of DisplaySettings. /// Description of DisplaySettings.
/// </summary> /// </summary>
public class DisplaySettings : INotifyPropertyChanged public class DisplaySettingsViewModel : INotifyPropertyChanged
{ {
public DisplaySettings() public DisplaySettingsViewModel()
{ {
this.selectedFont = new FontFamily("Consolas"); this.selectedFont = new FontFamily("Consolas");
this.selectedFontSize = 10.0 * 4 / 3; this.selectedFontSize = 10.0 * 4 / 3;
@ -312,7 +312,7 @@ namespace ICSharpCode.ILSpy.Options
} }
} }
public void CopyValues(DisplaySettings s) public void CopyValues(DisplaySettingsViewModel s)
{ {
this.SelectedFont = s.selectedFont; this.SelectedFont = s.selectedFont;
this.SelectedFontSize = s.selectedFontSize; this.SelectedFontSize = s.selectedFontSize;

31
ILSpy/Options/MiscSettingsPanel.xaml.cs

@ -19,6 +19,8 @@
using System.Windows.Controls; using System.Windows.Controls;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.Options namespace ICSharpCode.ILSpy.Options
{ {
/// <summary> /// <summary>
@ -37,44 +39,31 @@ namespace ICSharpCode.ILSpy.Options
this.DataContext = LoadMiscSettings(settings); this.DataContext = LoadMiscSettings(settings);
} }
static MiscSettings currentMiscSettings; static MiscSettingsViewModel currentMiscSettings;
public static MiscSettings CurrentMiscSettings { public static MiscSettingsViewModel CurrentMiscSettings {
get { get {
return currentMiscSettings ?? (currentMiscSettings = LoadMiscSettings(ILSpySettings.Load())); return currentMiscSettings ?? (currentMiscSettings = LoadMiscSettings(ILSpySettings.Load()));
} }
} }
public static MiscSettings LoadMiscSettings(ILSpySettings settings) public static MiscSettingsViewModel LoadMiscSettings(ILSpySettings settings)
{ {
XElement e = settings["MiscSettings"]; var s = MiscSettings.Load(settings);
var s = new MiscSettings(); return new MiscSettingsViewModel(s);
s.AllowMultipleInstances = (bool?)e.Attribute(nameof(s.AllowMultipleInstances)) ?? false;
s.LoadPreviousAssemblies = (bool?)e.Attribute(nameof(s.LoadPreviousAssemblies)) ?? true;
return s;
} }
public void Save(XElement root) public void Save(XElement root)
{ {
var s = (MiscSettings)this.DataContext; var s = (MiscSettingsViewModel)this.DataContext;
IMiscSettings.Save(root, s);
var section = new XElement("MiscSettings");
section.SetAttributeValue(nameof(s.AllowMultipleInstances), s.AllowMultipleInstances);
section.SetAttributeValue(nameof(s.LoadPreviousAssemblies), s.LoadPreviousAssemblies);
XElement existingElement = root.Element("MiscSettings");
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
currentMiscSettings = null; // invalidate cached settings currentMiscSettings = null; // invalidate cached settings
} }
public void LoadDefaults() public void LoadDefaults()
{ {
currentMiscSettings = new MiscSettings(); currentMiscSettings = new MiscSettingsViewModel(MiscSettings.Load(ILSpySettings.Load()));
this.DataContext = currentMiscSettings; this.DataContext = currentMiscSettings;
} }
} }

9
ILSpy/Options/MiscSettings.cs → ILSpy/Options/MiscSettingsViewModel.cs

@ -21,23 +21,26 @@ using System.ComponentModel;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Security.Principal;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using ICSharpCode.ILSpy.Commands; using ICSharpCode.ILSpy.Commands;
using ICSharpCode.ILSpyX.Settings;
using Microsoft.Win32; using Microsoft.Win32;
namespace ICSharpCode.ILSpy.Options namespace ICSharpCode.ILSpy.Options
{ {
public class MiscSettings : INotifyPropertyChanged public class MiscSettingsViewModel : IMiscSettings, INotifyPropertyChanged
{ {
bool allowMultipleInstances; bool allowMultipleInstances;
bool loadPreviousAssemblies = true; bool loadPreviousAssemblies = true;
public MiscSettings() public MiscSettingsViewModel(MiscSettings s)
{ {
AllowMultipleInstances = s.AllowMultipleInstances;
LoadPreviousAssemblies = s.LoadPreviousAssemblies;
AddRemoveShellIntegrationCommand = new DelegateCommand<object>(AddRemoveShellIntegration); AddRemoveShellIntegrationCommand = new DelegateCommand<object>(AddRemoveShellIntegration);
} }

1
ILSpy/Options/OptionsDialog.xaml.cs

@ -26,6 +26,7 @@ using System.Windows.Media;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy.Options namespace ICSharpCode.ILSpy.Options
{ {

1
ILSpy/SessionSettings.cs

@ -29,6 +29,7 @@ using System.Xml.Linq;
using ICSharpCode.ILSpy.Docking; using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Themes; using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpyX.Search; using ICSharpCode.ILSpyX.Search;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {

4
ILSpy/TextView/DecompilerTextView.cs

@ -174,11 +174,11 @@ namespace ICSharpCode.ILSpy.TextView
void CurrentDisplaySettings_PropertyChanged(object? sender, PropertyChangedEventArgs e) void CurrentDisplaySettings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(DisplaySettings.ShowLineNumbers)) if (e.PropertyName == nameof(DisplaySettingsViewModel.ShowLineNumbers))
{ {
ShowLineMargin(); ShowLineMargin();
} }
else if (e.PropertyName == nameof(DisplaySettings.HighlightCurrentLine)) else if (e.PropertyName == nameof(DisplaySettingsViewModel.HighlightCurrentLine))
{ {
SetHighlightCurrentLine(); SetHighlightCurrentLine();
} }

2
ILSpy/Themes/WindowStyleManagerBehavior.cs

@ -65,7 +65,7 @@ namespace ICSharpCode.ILSpy.Themes
private void DisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e) private void DisplaySettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(DisplaySettings.StyleWindowTitleBar)) if (e.PropertyName == nameof(DisplaySettingsViewModel.StyleWindowTitleBar))
{ {
if (!MainWindow.Instance.CurrentDisplaySettings.StyleWindowTitleBar) if (!MainWindow.Instance.CurrentDisplaySettings.StyleWindowTitleBar)
{ {

1
TestPlugin/CustomOptionPage.xaml.cs

@ -7,6 +7,7 @@ using System.Xml.Linq;
using ICSharpCode.ILSpy; using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpyX.Settings;
namespace TestPlugin namespace TestPlugin
{ {

Loading…
Cancel
Save