This commit is contained in:
Stephan Maier
2024-08-27 08:10:27 +02:00
parent eb5c2fa502
commit 647f938eee
617 changed files with 73086 additions and 7137 deletions

View File

@@ -0,0 +1,349 @@
// <copyright file="CustomSettingsProvider.cs" company="PlaceholderCompany">
// Copyright (c) PlaceholderCompany. All rights reserved.
// </copyright>
namespace FSI.BT.Tools.SystemTrayMenu.Properties
{
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using FSI.BT.Tools.Global.Utilities;
using FSI.BT.Tools.SystemTrayMenu.Utilities;
internal class CustomSettingsProvider : SettingsProvider
{
private const string NameOf = "name";
private const string SerializeAs = "serializeAs";
private const string Config = "configuration";
private const string UserSettings = "userSettings";
private const string Setting = "setting";
private bool loaded;
/// <summary>
/// Initializes a new instance of the <see cref="CustomSettingsProvider"/> class.
/// Loads the file into memory.
/// </summary>
public CustomSettingsProvider()
{
SettingsDictionary = new Dictionary<string, SettingStruct>();
}
/// <summary>
/// Gets the setting key this is returning must set before the settings are used.
/// e.g. <c>Properties.Settings.Default.SettingsKey = @"C:\temp\user.config";</c>.
/// </summary>
public static string UserConfigPath => Path.Combine(
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
$"FSI.BT.Tools.SystemTrayMenu"),
$"user-{Environment.MachineName}.config");
public static string ConfigPathAssembly => Path.Combine(
Directory.GetParent(Assembly.GetEntryAssembly().Location).FullName,
$"user.config");
/// <summary>
/// Gets or sets override.
/// </summary>
public override string ApplicationName
{
get => Assembly.GetExecutingAssembly().ManifestModule.Name;
set
{
// do nothing
}
}
/// <summary>
/// Gets or sets in memory storage of the settings values.
/// </summary>
private Dictionary<string, SettingStruct> SettingsDictionary { get; set; }
public static bool IsActivatedConfigPathAssembly()
{
return IsConfigPathAssembly();
}
public static void ActivateConfigPathAssembly()
{
CreateEmptyConfigIfNotExists(ConfigPathAssembly);
}
public static void DeactivateConfigPathAssembly()
{
if (IsConfigPathAssembly())
{
try
{
File.Delete(ConfigPathAssembly);
}
catch (Exception ex)
{
Log.Warn($"Could not delete {ConfigPathAssembly}", ex);
}
}
}
/// <summary>
/// Override.
/// </summary>
/// <param name="name">name.</param>
/// <param name="config">config.</param>
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
base.Initialize(ApplicationName, config);
}
/// <summary>
/// Must override this, this is the bit that matches up the designer properties to the dictionary values.
/// </summary>
/// <param name="context">context.</param>
/// <param name="collection">collection.</param>
/// <returns>SettingsPropertyValueCollection.</returns>
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
{
// load the file
if (!loaded)
{
loaded = true;
LoadValuesFromFile();
}
// collection that will be returned.
SettingsPropertyValueCollection values = new();
// itterate thought the properties we get from the designer, checking to see if the setting is in the dictionary
foreach (SettingsProperty setting in collection)
{
SettingsPropertyValue value = new(setting)
{
IsDirty = false,
};
// need the type of the value for the strong typing
Type t = Type.GetType(setting.PropertyType.FullName);
if (SettingsDictionary.ContainsKey(setting.Name))
{
value.SerializedValue = SettingsDictionary[setting.Name].Value;
value.PropertyValue = Convert.ChangeType(SettingsDictionary[setting.Name].Value, t, CultureInfo.InvariantCulture);
}
else
{
// use defaults in the case where there are no settings yet
value.SerializedValue = setting.DefaultValue;
value.PropertyValue = Convert.ChangeType(setting.DefaultValue, t, CultureInfo.InvariantCulture);
}
values.Add(value);
}
return values;
}
/// <summary>
/// Must override this, this is the bit that does the saving to file. Called when Settings.Save() is called.
/// </summary>
/// <param name="context">context.</param>
/// <param name="collection">collection.</param>
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
{
// grab the values from the collection parameter and update the values in our dictionary.
foreach (SettingsPropertyValue value in collection)
{
SettingStruct setting = new()
{
Value = value.PropertyValue == null ? string.Empty : value.PropertyValue.ToString(),
Name = value.Name,
SerializeAs = value.Property.SerializeAs.ToString(),
};
if (!SettingsDictionary.ContainsKey(value.Name))
{
SettingsDictionary.Add(value.Name, setting);
}
else
{
SettingsDictionary[value.Name] = setting;
}
}
// now that our local dictionary is up-to-date, save it to disk.
SaveValuesToFile();
}
/// <summary>
/// Creates an empty user.config file...looks like the one MS creates.
/// This could be overkill a simple key/value pairing would probably do.
/// </summary>
private static void CreateEmptyConfigIfNotExists(string path)
{
if (!File.Exists(path))
{
// if the config file is not where it's supposed to be create a new one.
XDocument doc = new();
XDeclaration declaration = new("1.0", "utf-8", "true");
XElement config = new(Config);
XElement userSettings = new(UserSettings);
//XElement group = new(typeof(Settings).FullName);
//userSettings.Add(group);
config.Add(userSettings);
doc.Add(config);
doc.Declaration = declaration;
try
{
doc.Save(path);
}
catch (Exception ex)
{
Log.Warn($"Failed to store config at assembly location {path}", ex);
}
}
}
private static bool IsConfigPathAssembly()
{
bool isconfigPathAssembly = false;
try
{
isconfigPathAssembly = File.Exists(ConfigPathAssembly);
}
catch (Exception ex)
{
Log.Warn("IsConfigPathAssembly failed", ex);
}
return isconfigPathAssembly;
}
private static XDocument LoadOrGetNew(string path)
{
XDocument xDocument = null;
try
{
xDocument = XDocument.Load(path);
}
catch (Exception exceptionWarning)
{
Log.Warn($"Could not load {path}", exceptionWarning);
try
{
File.Delete(path);
CreateEmptyConfigIfNotExists(path);
xDocument = XDocument.Load(path);
}
catch (Exception exceptionError)
{
Log.Error($"Could not delete and create {path}", exceptionError);
}
}
return xDocument;
}
/// <summary>
/// Loads the values of the file into memory.
/// </summary>
private void LoadValuesFromFile()
{
CreateEmptyConfigIfNotExists(UserConfigPath);
// load the xml
XDocument configXml;
if (IsConfigPathAssembly())
{
configXml = LoadOrGetNew(ConfigPathAssembly);
}
else
{
configXml = LoadOrGetNew(UserConfigPath);
}
if (configXml != null)
{
// get all of the <setting name="..." serializeAs="..."> elements.
//IEnumerable<XElement> settingElements = configXml.Element(Config).Element(UserSettings).Element(typeof(Settings).FullName).Elements(Setting);
// iterate through, adding them to the dictionary, (checking for nulls, xml no likey nulls)
// using "String" as default serializeAs...just in case, no real good reason.
//foreach (XElement element in settingElements)
//{
// SettingStruct newSetting = new()
// {
// Name = element.Attribute(NameOf) == null ? string.Empty : element.Attribute(NameOf).Value,
// SerializeAs = element.Attribute(SerializeAs) == null ? "String" : element.Attribute(SerializeAs).Value,
// Value = element.Value ?? string.Empty,
// };
// SettingsDictionary.Add(element.Attribute(NameOf).Value, newSetting);
//}
}
}
/// <summary>
/// Saves the in memory dictionary to the user config file.
/// </summary>
private void SaveValuesToFile()
{
// load the current xml from the file.
XDocument configXml;
if (IsConfigPathAssembly())
{
configXml = LoadOrGetNew(ConfigPathAssembly);
}
else
{
configXml = LoadOrGetNew(UserConfigPath);
}
if (configXml != null)
{
// get the settings group (e.g. <Company.Project.Desktop.Settings>)
//XElement settingsSection = configXml.Element(Config).Element(UserSettings).Element(typeof(Settings).FullName);
// iterate though the dictionary, either updating the value or adding the new setting.
//foreach (KeyValuePair<string, SettingStruct> entry in SettingsDictionary)
//{
// XElement setting = settingsSection.Elements().FirstOrDefault(e => e.Attribute(NameOf).Value == entry.Key);
// if (setting == null)
// {
// // this can happen if a new setting is added via the .settings designer.
// XElement newSetting = new(Setting);
// newSetting.Add(new XAttribute(NameOf, entry.Value.Name));
// newSetting.Add(new XAttribute(SerializeAs, entry.Value.SerializeAs));
// newSetting.Value = entry.Value.Value ?? string.Empty;
// settingsSection.Add(newSetting);
// }
// else
// {
// // update the value if it exists.
// setting.Value = entry.Value.Value ?? string.Empty;
// }
//}
if (IsConfigPathAssembly())
{
configXml.Save(ConfigPathAssembly);
}
configXml.Save(UserConfigPath);
}
}
/// <summary>
/// Helper struct.
/// </summary>
internal struct SettingStruct
{
internal string Name;
internal string SerializeAs;
internal string Value;
}
}
}

View File

@@ -0,0 +1,173 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace FSI.BT.Tools.SystemTrayMenu.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FSI.BT.Tools.SystemTrayMenu.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] ic_fluent_arrow_sync_24_regular {
get {
object obj = ResourceManager.GetObject("ic_fluent_arrow_sync_24_regular", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] ic_fluent_folder_arrow_right_48_regular {
get {
object obj = ResourceManager.GetObject("ic_fluent_folder_arrow_right_48_regular", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] ic_fluent_pin_48_filled {
get {
object obj = ResourceManager.GetObject("ic_fluent_pin_48_filled", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] ic_fluent_pin_48_regular {
get {
object obj = ResourceManager.GetObject("ic_fluent_pin_48_regular", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] ic_fluent_search_48_regular {
get {
object obj = ResourceManager.GetObject("ic_fluent_search_48_regular", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
public static byte[] ic_fluent_settings_28_regular {
get {
object obj = ResourceManager.GetObject("ic_fluent_settings_28_regular", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
public static System.Drawing.Icon LinkArrow {
get {
object obj = ResourceManager.GetObject("LinkArrow", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
public static System.Drawing.Icon Loading {
get {
object obj = ResourceManager.GetObject("Loading", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
public static System.Drawing.Icon NotFound {
get {
object obj = ResourceManager.GetObject("NotFound", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
public static System.Drawing.Icon SystemTrayMenu {
get {
object obj = ResourceManager.GetObject("FSI.BT.Tools.SystemTrayMenu", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>
public static System.Drawing.Icon White50Percentage {
get {
object obj = ResourceManager.GetObject("White50Percentage", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
}
}

View File

@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="White50Percentage" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\White50Percentage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ic_fluent_pin_48_filled" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ic_fluent_pin_48_filled.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="ic_fluent_pin_48_regular" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ic_fluent_pin_48_regular.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="ic_fluent_search_48_regular" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ic_fluent_search_48_regular.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="ic_fluent_folder_arrow_right_48_regular" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ic_fluent_folder_arrow_right_48_regular.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="NotFound" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\NotFound.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Loading" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Loading.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ic_fluent_arrow_sync_24_regular" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ic_fluent_arrow_sync_24_regular.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="ic_fluent_settings_28_regular" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ic_fluent_settings_28_regular.svg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="LinkArrow" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\LinkArrow.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="FSI.BT.Tools.SystemTrayMenu" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\Global\Icons\FondiumU.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>