diff --git a/Deploy/MFD4CTS_2_6_1_RC..zip b/Deploy/MFD4CTS_2_6_1_RC..zip new file mode 100644 index 0000000..e366aee Binary files /dev/null and b/Deploy/MFD4CTS_2_6_1_RC..zip differ diff --git a/Deploy/MFD4CTS_2_6_BetaInstall.zip b/Deploy/MFD4CTS_2_6_BetaInstall.zip new file mode 100644 index 0000000..1981f66 Binary files /dev/null and b/Deploy/MFD4CTS_2_6_BetaInstall.zip differ diff --git a/MFDSettingsManager/Configuration/Collections/ConfigurationCollection.cs b/MFDSettingsManager/Configuration/Collections/ConfigurationCollection.cs new file mode 100644 index 0000000..3d1b883 --- /dev/null +++ b/MFDSettingsManager/Configuration/Collections/ConfigurationCollection.cs @@ -0,0 +1,22 @@ +using System; + +namespace MFDSettingsManager.Configuration.Collections +{ + /// + /// Collection of MFD configurations + /// + public class ConfigurationCollection : ConfigurationSectionCollectionBase + { + /// + /// Definition of a key + /// + /// + protected override Func GetDefaultKey() + { + return (element) => + { + return element.Name + element.FileName; + }; + } + } +} \ No newline at end of file diff --git a/MFDSettingsManager/Configuration/Collections/ConfigurationSectionCollectionBase.cs b/MFDSettingsManager/Configuration/Collections/ConfigurationSectionCollectionBase.cs new file mode 100644 index 0000000..a6019fc --- /dev/null +++ b/MFDSettingsManager/Configuration/Collections/ConfigurationSectionCollectionBase.cs @@ -0,0 +1,189 @@ +using log4net; +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Xml; + +namespace MFDSettingsManager.Configuration.Collections +{ + /// + /// Base class for all ConfigurationSectionCollection + /// + /// + public class ConfigurationSectionCollectionBase : ConfigurationElementCollection where T : ConfigurationElement, new() + { + #region Properties + + /// + /// Logger to use + /// + protected ILog Logger => LogManager.GetLogger("MFD4CTS"); + + #endregion Properties + + #region Overrides to permit error logging + + /// + /// Error deserializing an attribute + /// + /// + /// + /// + protected override bool OnDeserializeUnrecognizedAttribute(string name, string value) + { + Logger?.Error($"Unrecognized attribute named: {name} with value: {value}"); + return base.OnDeserializeUnrecognizedAttribute(name, value); + } + + /// + /// Logs an unrecognized element + /// + /// + /// + /// + protected override bool OnDeserializeUnrecognizedElement(string elementName, XmlReader reader) + { + Logger?.Error($"Unrecognized element named: {elementName} location: {ElementInformation.Source}"); + return base.OnDeserializeUnrecognizedElement(elementName, reader); + } + + /// + /// Logs a required property missing + /// + /// + /// + protected override object OnRequiredPropertyNotFound(string name) + { + Logger?.Error($"Required property missing named: {name}."); + return base.OnRequiredPropertyNotFound(name); + } + + #endregion Overrides to permit error logging + + #region Collection item access + + /// + /// Exposes the Collection as a List + /// + public List List => GetAsList(); + + /// + /// Access collection item by index + /// + /// + /// + public T this[int index] + { + get + { + return BaseGet(index) as T; + } + set + { + if (BaseGet(index) != null) + { + BaseRemoveAt(index); + } + BaseAdd(index, value); + } + } + + /// + /// Access collection item by key + /// + /// + /// + public new T this[string key] + { + get { return (T)BaseGet(key); } + set + { + if (BaseGet(key) != null) + { + BaseRemoveAt(BaseIndexOf(BaseGet(key))); + } + BaseAdd(value); + } + } + + /// + /// Public add needed to provide a method for adding items to the collection + /// + /// + public void Add(T definition) + { + BaseAdd(definition); + } + + /// + /// Public remove method to provide a method for removing items from the collection + /// + /// + public void Remove(T definition) + { + BaseRemove(GetCompositeKey); + } + + #endregion Collection item access + + #region Create new element for the collection + + /// + /// Creates a new element for the collection + /// + /// + protected override ConfigurationElement CreateNewElement() + { + return new T(); + } + + #endregion Create new element for the collection + + #region Key and item management + + /// + /// Function to define how we get a key + /// + public Func GetCompositeKey => GetDefaultKey(); + + /// + /// Default implementation returns empty string + /// + /// + protected virtual Func GetDefaultKey() + { + return (T) => ""; + } + + /// + /// Each unique entry is Name+FileName + /// + /// + /// + protected override object GetElementKey(ConfigurationElement element) + { + return GetCompositeKey?.Invoke((T)element) ?? ""; + } + + #endregion Key and item management + + #region Private helpers + + private List GetAsList() + { + var defList = new List(); + + var iterator = this.GetEnumerator(); + while (iterator.MoveNext()) + { + defList.Add((T)iterator.Current); + } + + return defList; + } + + + #endregion Private helpers + } +} + diff --git a/MFDSettingsManager/Configuration/Collections/ModulesConfigurationCollection.cs b/MFDSettingsManager/Configuration/Collections/ModulesConfigurationCollection.cs new file mode 100644 index 0000000..3a68df6 --- /dev/null +++ b/MFDSettingsManager/Configuration/Collections/ModulesConfigurationCollection.cs @@ -0,0 +1,23 @@ +using System; + +namespace MFDSettingsManager.Configuration.Collections +{ + /// + /// Module configuration collection + /// + public class ModulesConfigurationCollection : ConfigurationSectionCollectionBase + { + /// + /// Definition of a key + /// + /// + protected override Func GetDefaultKey() + { + return (element) => + { + return element.ModuleName; + }; + + } + } +} \ No newline at end of file diff --git a/MFDSettingsManager/Configuration/Collections/SubConfigurationCollection.cs b/MFDSettingsManager/Configuration/Collections/SubConfigurationCollection.cs new file mode 100644 index 0000000..a4c9226 --- /dev/null +++ b/MFDSettingsManager/Configuration/Collections/SubConfigurationCollection.cs @@ -0,0 +1,22 @@ +using System; + +namespace MFDSettingsManager.Configuration.Collections +{ + /// + /// + /// + public class SubConfigurationCollection : ConfigurationSectionCollectionBase + { + /// + /// Definition of a key + /// + /// + protected override Func GetDefaultKey() + { + return (subconfig) => + { + return subconfig.Name; + }; + } + } +} \ No newline at end of file diff --git a/MFDSettingsManager/Configuration/Elements/Configuration.cs b/MFDSettingsManager/Configuration/Elements/Configuration.cs new file mode 100644 index 0000000..f472678 --- /dev/null +++ b/MFDSettingsManager/Configuration/Elements/Configuration.cs @@ -0,0 +1,136 @@ +using MFDSettingsManager.Configuration.Collections; +using System; +using System.Configuration; + +namespace MFDSettingsManager.Configuration +{ + /// + /// Encapsulates a MFD configuration + /// + public class Configuration : ConfigurationBase + { + + /// + /// Default constructor + /// + public Configuration() + { + } + + /// + /// Sub-Configurations + /// + [ConfigurationProperty("SubConfigurations", IsDefaultCollection = false)] + [ConfigurationCollection(typeof(SubConfigurationCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] + public SubConfigurationCollection SubConfigurations + { + get + { + object o = this["SubConfigurations"]; + return o as SubConfigurationCollection; + } + + set + { + this["SubConfigurations"] = value; + } + } + + + /// + /// Copy constructor + /// + /// + public Configuration(Configuration dc) : base(dc) + { + Height = dc.Height; + Width = dc.Width; + Left = dc.Left; + Top = dc.Top; + } + + #region Left, Top, Wdith and Height + + /// + /// Nullable Width of the image in the display, used to override the default + /// + [ConfigurationProperty("width", IsRequired = false)] + public int? Width + { + get + { + if (this["width"] == null) + { + return null; + } + return (int)Convert.ChangeType(this["width"], typeof(int)); + } + set + { + this["width"] = value; + } + } + + /// + /// Nullable Height of the image in the display, used to override the default + /// + [ConfigurationProperty("height", IsRequired = false)] + public int? Height + { + get + { + if (this["height"] == null) + { + return null; + } + return (int)Convert.ChangeType(this["height"], typeof(int)); + } + set + { + this["height"] = value; + } + } + + /// + /// Nullable Left position of the image in the display + /// + [ConfigurationProperty("left", IsRequired = false)] + public int? Left + { + get + { + if (this["left"] == null) + { + return null; + } + return (int)Convert.ChangeType(this["left"], typeof(int)); + } + set + { + this["left"] = value; + } + } + + /// + /// Nullable Top position of the image in the display + /// + [ConfigurationProperty("top", IsRequired = false)] + public int? Top + { + get + { + if (this["top"] == null) + { + return null; + } + return (int)Convert.ChangeType(this["top"], typeof(int)); + } + set + { + this["top"] = value; + } + } + + #endregion Left, Top, Wdith and Height + } +} \ No newline at end of file diff --git a/MFDSettingsManager/Configuration/MFDDefintion.cs b/MFDSettingsManager/Configuration/Elements/ConfigurationBase.cs similarity index 65% rename from MFDSettingsManager/Configuration/MFDDefintion.cs rename to MFDSettingsManager/Configuration/Elements/ConfigurationBase.cs index 87f8aca..1074e04 100644 --- a/MFDSettingsManager/Configuration/MFDDefintion.cs +++ b/MFDSettingsManager/Configuration/Elements/ConfigurationBase.cs @@ -4,29 +4,25 @@ namespace MFDSettingsManager.Configuration { /// - /// Encapsulates a MFD configuration + /// Base class for all configuration types /// - public class MFDDefintion : ConfigurationElement + public abstract class ConfigurationBase : ConfigurationElement { - /// /// Default constructor /// - public MFDDefintion() + public ConfigurationBase() { + } /// - /// Copy constructor + /// Base copy constructor /// /// - public MFDDefintion(MFDDefintion dc) + public ConfigurationBase(ConfigurationBase dc) { FileName = dc.FileName; - Height = dc.Height; - Width = dc.Width; - Left = dc.Left; - Top = dc.Top; Name = dc.Name; Enabled = dc.Enabled ?? true; XOffsetStart = dc.XOffsetStart; @@ -109,90 +105,6 @@ public string FileName #endregion General configuration properties - #region Left, Top, Wdith and Height - - /// - /// Nullable Width of the image in the display, used to override the default - /// - [ConfigurationProperty("width", IsRequired = false)] - public int? Width - { - get - { - if (this["width"] == null) - { - return null; - } - return (int)Convert.ChangeType(this["width"], typeof(int)); - } - set - { - this["width"] = value; - } - } - - /// - /// Nullable Height of the image in the display, used to override the default - /// - [ConfigurationProperty("height", IsRequired = false)] - public int? Height - { - get - { - if (this["height"] == null) - { - return null; - } - return (int)Convert.ChangeType(this["height"], typeof(int)); - } - set - { - this["height"] = value; - } - } - - /// - /// Nullable Left position of the image in the display - /// - [ConfigurationProperty("left", IsRequired = false)] - public int? Left - { - get - { - if (this["left"] == null) - { - return null; - } - return (int)Convert.ChangeType(this["left"], typeof(int)); - } - set - { - this["left"] = value; - } - } - - /// - /// Nullable Top position of the image in the display - /// - [ConfigurationProperty("top", IsRequired = false)] - public int? Top - { - get - { - if (this["top"] == null) - { - return null; - } - return (int)Convert.ChangeType(this["top"], typeof(int)); - } - set - { - this["top"] = value; - } - } - - #endregion Left, Top, Wdith and Height - #region X Offsets /// @@ -267,7 +179,7 @@ public int? YOffsetFinish { get { - if(this["yOffsetFinish"] == null) + if (this["yOffsetFinish"] == null) { return null; } @@ -281,4 +193,4 @@ public int? YOffsetFinish #endregion Y Offsets } -} \ No newline at end of file +} diff --git a/MFDSettingsManager/Configuration/ModuleConfigurationDefintion.cs b/MFDSettingsManager/Configuration/Elements/ModuleConfiguration.cs similarity index 79% rename from MFDSettingsManager/Configuration/ModuleConfigurationDefintion.cs rename to MFDSettingsManager/Configuration/Elements/ModuleConfiguration.cs index d4cb314..1789963 100644 --- a/MFDSettingsManager/Configuration/ModuleConfigurationDefintion.cs +++ b/MFDSettingsManager/Configuration/Elements/ModuleConfiguration.cs @@ -1,4 +1,5 @@ -using System; +using MFDSettingsManager.Configuration.Collections; +using System; using System.Configuration; namespace MFDSettingsManager.Configuration @@ -6,7 +7,7 @@ namespace MFDSettingsManager.Configuration /// /// Module configuration /// - public class ModuleConfigurationDefintion : ConfigurationElement + public class ModuleConfiguration : ConfigurationElement { #region Module configuration properties @@ -66,13 +67,13 @@ public string FileName /// MFD Configurations /// [ConfigurationProperty("Configurations", IsDefaultCollection = true)] - [ConfigurationCollection(typeof(MFDDefinitionsCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] - public MFDDefinitionsCollection MFDConfigurations + [ConfigurationCollection(typeof(ConfigurationCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] + public ConfigurationCollection Configurations { get { object o = this["Configurations"]; - return o as MFDDefinitionsCollection; + return o as ConfigurationCollection; } set @@ -86,12 +87,12 @@ public MFDDefinitionsCollection MFDConfigurations /// /// /// - public MFDDefintion GetMFDConfiguration(string name) + public Configuration GetMFDConfiguration(string name) { - var iterator = MFDConfigurations.GetEnumerator(); + var iterator = Configurations.GetEnumerator(); while(iterator.MoveNext()) { - var currentConfig = (MFDDefintion) iterator.Current; + var currentConfig = (Configuration) iterator.Current; if(currentConfig.Name == name) { return currentConfig; diff --git a/MFDSettingsManager/Configuration/Elements/SubConfiguration.cs b/MFDSettingsManager/Configuration/Elements/SubConfiguration.cs new file mode 100644 index 0000000..91eec3b --- /dev/null +++ b/MFDSettingsManager/Configuration/Elements/SubConfiguration.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace MFDSettingsManager.Configuration +{ + /// + /// + /// + public class SubConfiguration : ConfigurationBase + { + /// + /// Default constructor + /// + public SubConfiguration() + { + + } + + /// + /// Copy constructor + /// + /// + public SubConfiguration(SubConfiguration dc) : base(dc) + { + StartX = dc.StartX; + StartY = dc.StartY; + EndX = dc.EndX; + EndY = dc.EndY; + } + + + #region startX, startY, endX and endY + + /// + /// Starting X position + /// + [ConfigurationProperty("startX", IsRequired = false)] + public int? StartX + { + get + { + if (this["startX"] == null) + { + return null; + } + + return (int)Convert.ChangeType(this["startX"], typeof(int)); + } + set + { + this["startX"] = value; + } + } + + /// + /// Starting Y position + /// + [ConfigurationProperty("startY", IsRequired = false)] + public int? StartY + { + get + { + if (this["startY"] == null) + { + return null; + } + + return (int)Convert.ChangeType(this["startY"], typeof(int)); + } + set + { + this["startY"] = value; + } + } + + /// + /// ending X position + /// + [ConfigurationProperty("endX", IsRequired = false)] + public int? EndX + { + get + { + if (this["endX"] == null) + { + return null; + } + + return (int)Convert.ChangeType(this["endX"], typeof(int)); + } + set + { + this["endX"] = value; + } + } + + /// + /// ending Y position + /// + [ConfigurationProperty("endY", IsRequired = false)] + public int? EndY + { + get + { + if (this["endY"] == null) + { + return null; + } + + return (int)Convert.ChangeType(this["endY"], typeof(int)); + } + set + { + this["endY"] = value; + } + } + + + #endregion startX, startY, endX and endY + } +} \ No newline at end of file diff --git a/MFDSettingsManager/Configuration/MFDConfigurationSection.cs b/MFDSettingsManager/Configuration/MFDConfigurationSection.cs index ccfd067..286ee83 100644 --- a/MFDSettingsManager/Configuration/MFDConfigurationSection.cs +++ b/MFDSettingsManager/Configuration/MFDConfigurationSection.cs @@ -1,4 +1,5 @@ using log4net; +using MFDSettingsManager.Configuration.Collections; using System; using System.Configuration; using System.IO; @@ -35,7 +36,7 @@ public static MFDConfigurationSection GetConfig(ILog logger, string fullPathtoCo System.Configuration.Configuration currentConfiguration = null; - if(string.IsNullOrEmpty(fullPathtoConfig)) + if (string.IsNullOrEmpty(fullPathtoConfig)) { var exeAssem = Assembly.GetEntryAssembly(); currentConfiguration = ConfigurationManager.OpenExeConfiguration(exeAssem.Location); @@ -62,7 +63,6 @@ public static MFDConfigurationSection GetConfig(ILog logger, string fullPathtoCo } return null; - } #region Properties to support schema definitions @@ -119,23 +119,6 @@ internal set #region Main configuration properties - /// - /// SaveClips results in the cropped images being saved - /// - [ConfigurationProperty("saveClips", IsRequired = false)] - public bool? SaveClips - { - get - { - return (bool?)this["saveClips"]; - } - set - { - IsDataDirty = true; - this["saveClips"] = value; - } - } - /// /// The file path to the images to be cropped /// @@ -178,13 +161,13 @@ public string DefaultConfig /// MFD Default Configurations /// [ConfigurationProperty("DefaultConfigurations", IsDefaultCollection = false, IsRequired = false)] - [ConfigurationCollection(typeof(MFDDefinitionsCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] - public MFDDefinitionsCollection DefaultConfigurations + [ConfigurationCollection(typeof(ConfigurationCollection), AddItemName = "add", ClearItemsName = "clear", RemoveItemName = "remove")] + public ConfigurationCollection DefaultConfigurations { get { object o = this["DefaultConfigurations"]; - return o as MFDDefinitionsCollection; + return o as ConfigurationCollection; } set diff --git a/MFDSettingsManager/Configuration/MFDDefinitionsCollection.cs b/MFDSettingsManager/Configuration/MFDDefinitionsCollection.cs deleted file mode 100644 index 91f9195..0000000 --- a/MFDSettingsManager/Configuration/MFDDefinitionsCollection.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System.Collections.Generic; -using System.Configuration; - -namespace MFDSettingsManager.Configuration -{ - /// - /// Collection of MFD configurations - /// - public class MFDDefinitionsCollection : ConfigurationElementCollection - { - - /// - /// Exposes the Collection as a List - /// - public List List => GetAsList(); - - private List GetAsList() - { - var defList = new List(); - - var iterator = this.GetEnumerator(); - while(iterator.MoveNext()) - { - defList.Add((MFDDefintion) iterator.Current); - } - - return defList; - } - - #region Collection item access - - /// - /// Access collection item by index - /// - /// - /// - public MFDDefintion this[int index] - { - get - { - return BaseGet(index) as MFDDefintion; - } - set - { - if (BaseGet(index) != null) - { - BaseRemoveAt(index); - } - BaseAdd(index, value); - } - } - - /// - /// Access collection item by key - /// - /// - /// - public new MFDDefintion this[string key] - { - get { return (MFDDefintion)BaseGet(key); } - set - { - if (BaseGet(key) != null) - { - BaseRemoveAt(BaseIndexOf(BaseGet(key))); - } - BaseAdd(value); - } - } - - #endregion Collection item access - - #region Create new element for the collection - - /// - /// Creates a new element for the collection - /// - /// - protected override ConfigurationElement CreateNewElement() - { - return new MFDDefintion(); - } - - #endregion Create new element for the collection - - #region Key and item management - - /// - /// Each unique entry is Name+FileName - /// - /// - /// - protected override object GetElementKey(ConfigurationElement element) - { - return ((MFDDefintion)element).Name + ((MFDDefintion)element).FileName; - } - - /// - /// Public add needed to provide a method for adding items to the collection - /// - /// - public void Add(MFDDefintion definition) - { - BaseAdd(definition); - } - - /// - /// Public remove needed to provide a method for removing items from the collection - /// - /// - public void Remove(MFDDefintion defintion) - { - BaseRemove(defintion.Name + defintion.FileName); - } - - #endregion Key and item management - } -} \ No newline at end of file diff --git a/MFDSettingsManager/Configuration/ModulesConfigurationCollection.cs b/MFDSettingsManager/Configuration/ModulesConfigurationCollection.cs deleted file mode 100644 index 4b64dcf..0000000 --- a/MFDSettingsManager/Configuration/ModulesConfigurationCollection.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Collections.Generic; -using System.Configuration; - -namespace MFDSettingsManager.Configuration -{ - /// - /// Module configuration collection - /// - public class ModulesConfigurationCollection : ConfigurationElementCollection - { - /// - /// Exposes the Collection as a List - /// - public List List => GetAsList(); - - private List GetAsList() - { - var defList = new List(); - - var iterator = this.GetEnumerator(); - while (iterator.MoveNext()) - { - defList.Add((ModuleConfigurationDefintion)iterator.Current); - } - - return defList; - } - - #region Collection item access - - /// - /// Access collection item by index - /// - /// - /// - public ModuleConfigurationDefintion this[int index] - { - get - { - return BaseGet(index) as ModuleConfigurationDefintion; - } - set - { - if (BaseGet(index) != null) - { - BaseRemoveAt(index); - } - BaseAdd(index, value); - } - } - - /// - /// Access collection item by key - /// - /// - /// - public new ModuleConfigurationDefintion this[string key] - { - get { return (ModuleConfigurationDefintion)BaseGet(key); } - set - { - if (BaseGet(key) != null) - { - BaseRemoveAt(BaseIndexOf(BaseGet(key))); - } - BaseAdd(value); - } - } - - #endregion Collection item access - - #region Create new element for the collection - - /// - /// Creates a new element for the collection - /// - /// - protected override ConfigurationElement CreateNewElement() - { - return new ModuleConfigurationDefintion(); - } - - #endregion Create new element for the collection - - #region Key and item management - - /// - /// Each unique entry is IntegrationType+SubWorkflowKey - /// - /// - /// - protected override object GetElementKey(ConfigurationElement element) - { - return ((ModuleConfigurationDefintion)element).ModuleName; - } - - /// - /// Public add needed to provide a method for adding items to the collection - /// - /// - public void Add(ModuleConfigurationDefintion definition) - { - BaseAdd(definition); - } - - /// - /// Public remove needed to provide a method for removing items from the collection - /// - /// - public void Remove(ModuleConfigurationDefintion defintion) - { - BaseRemove(defintion.ModuleName); - } - - #endregion Key and item management - } -} \ No newline at end of file diff --git a/MFDSettingsManager/MFDSettingsManager.csproj b/MFDSettingsManager/MFDSettingsManager.csproj index fa905ea..a4a9bad 100644 --- a/MFDSettingsManager/MFDSettingsManager.csproj +++ b/MFDSettingsManager/MFDSettingsManager.csproj @@ -51,19 +51,25 @@ + + + + - - + + + - - + + + diff --git a/MFDSettingsManager/Mappers/ConfigSectionModelMapper.cs b/MFDSettingsManager/Mappers/ConfigSectionModelMapper.cs index b625f73..03a21d1 100644 --- a/MFDSettingsManager/Mappers/ConfigSectionModelMapper.cs +++ b/MFDSettingsManager/Mappers/ConfigSectionModelMapper.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading.Tasks; namespace MFDSettingsManager.Mappers { @@ -45,7 +44,7 @@ internal static ModulesConfiguration MapFromConfigurationSection(MFDConfiguratio var modelModule = ConvertFromConfigSectionModule(moduleConfigurations, currentModule); // Add the Configurations - currentModule.MFDConfigurations.List.ForEach(currentConfig => + currentModule.Configurations.List.ForEach(currentConfig => { var mfdConfiguration = ConvertFromConfigSectionDefinition(section, modelModule, currentConfig); logger.Info($"Loading Configuration {mfdConfiguration.ToReadableString()}..."); @@ -60,7 +59,6 @@ internal static ModulesConfiguration MapFromConfigurationSection(MFDConfiguratio dc.Logger = logger; dc.ModuleName = modelModule.ModuleName; dc.FileName = !string.IsNullOrEmpty(modelModule.FileName) ? modelModule.FileName : dc.FileName; - dc.SaveResults = dc.SaveResults ?? section.SaveClips ?? false; logger.Info($"Adding default configuration {dc.ToReadableString()}..."); var newMfdConfiguration = new ConfigurationDefinition(dc) { @@ -80,7 +78,6 @@ internal static ModulesConfiguration MapFromConfigurationSection(MFDConfiguratio existConfig.YOffsetStart = existConfig.YOffsetStart == 0 ? dc.YOffsetStart : existConfig.YOffsetStart; existConfig.YOffsetFinish = existConfig.YOffsetFinish == 0 ? dc.YOffsetFinish : existConfig.YOffsetFinish; existConfig.FileName = string.IsNullOrEmpty(existConfig.FileName) ? dc.FileName : existConfig.FileName; - existConfig.SaveResults = existConfig.SaveResults ?? dc.SaveResults ?? false; existConfig.ModuleName = modelModule.ModuleName; existConfig.FilePath = section.FilePath; var completePath = Path.Combine(section.FilePath, existConfig.FileName); @@ -133,12 +130,11 @@ private static ModulesConfiguration ConvertFromConfigSection(MFDConfigurationSec { Logger = section.Logger, FilePath = section.FilePath, - DefaultConfig = section.DefaultConfig, - SaveClips = section.SaveClips ?? false, + DefaultConfig = section.DefaultConfig }; } - private static ModuleDefinition ConvertFromConfigSectionModule(ModulesConfiguration parent, ModuleConfigurationDefintion module) + private static ModuleDefinition ConvertFromConfigSectionModule(ModulesConfiguration parent, ModuleConfiguration module) { return new ModuleDefinition() { @@ -149,9 +145,9 @@ private static ModuleDefinition ConvertFromConfigSectionModule(ModulesConfigurat }; } - private static ConfigurationDefinition ConvertFromConfigSectionDefinition(MFDConfigurationSection section, ModuleDefinition parent, MFDDefintion currentConfig) + private static ConfigurationDefinition ConvertFromConfigSectionDefinition(MFDConfigurationSection section, ModuleDefinition parent, Configuration.Configuration currentConfig) { - return new ConfigurationDefinition() + var config = new ConfigurationDefinition() { Logger = section.Logger, ModuleName = parent?.ModuleName, @@ -168,9 +164,34 @@ private static ConfigurationDefinition ConvertFromConfigSectionDefinition(MFDCon YOffsetStart = currentConfig.YOffsetStart ?? 0, YOffsetFinish = currentConfig.YOffsetFinish ?? 0, Enabled = currentConfig.Enabled ?? true, - SaveResults = section.SaveClips - }; + SubConfigurations = new List() + }; + + currentConfig.SubConfigurations.List.ForEach((subConfig) => + { + var currentSubConfig = new SubConfigurationDefinition() + { + Enabled = subConfig.Enabled ?? currentConfig.Enabled ?? true, + EndX = subConfig.EndX ?? 0, + EndY = subConfig.EndY ?? 0, + StartX = subConfig.StartX ?? 0, + StartY = subConfig.StartY ?? 0, + FileName = subConfig.FileName ?? currentConfig.FileName ?? parent.FileName, + FilePath = section.FilePath, + Logger = section.Logger, + ModuleName = parent?.ModuleName, + Name = subConfig.Name, + Opacity = subConfig.Opacity ?? 0, + XOffsetStart = subConfig.XOffsetStart ?? 0, + XOffsetFinish = subConfig.XOffsetFinish ?? 0, + YOffsetStart = subConfig.YOffsetStart ?? 0, + YOffsetFinish = subConfig.YOffsetFinish ?? 0 + }; + + config.SubConfigurations.Add(currentSubConfig); + }); + return config; } } } diff --git a/MFDSettingsManager/Models/ConfigurationDefinition.cs b/MFDSettingsManager/Models/ConfigurationDefinition.cs index 3ee3775..cfbd45f 100644 --- a/MFDSettingsManager/Models/ConfigurationDefinition.cs +++ b/MFDSettingsManager/Models/ConfigurationDefinition.cs @@ -1,56 +1,40 @@ -using log4net; -using MFDSettingsManager.Enum; -using MFDSettingsManager.Extensions; -using System; +using System; +using System.Collections.Generic; using System.IO; -using System.Windows; -using System.Windows.Media; -using System.Windows.Media.Imaging; namespace MFDSettingsManager.Models { /// /// Single Configuration for a Module /// - public class ConfigurationDefinition + public class ConfigurationDefinition : ConfigurationModelBase { - /// - /// Logger - /// - public ILog Logger { get; set; } + #region Ctor - #region Identifying properties /// - /// Module Name - /// - public string ModuleName { get; set; } - /// - /// Name of the Configuration - /// - public string Name { get; set; } - /// - /// FileName for the image cropping that this configuration uses + /// Default constructor /// - public string FileName { get; set; } + public ConfigurationDefinition() + { - /// - /// The starting file path for the configuration - /// - public string FilePath { get; set; } + } /// - /// Determines if the configuration is rendered + /// Copy constructor /// - public bool Enabled { get; internal set; } + /// + public ConfigurationDefinition(ConfigurationDefinition dc) : base(dc) + { + Left = dc.Left; + Top = dc.Top; + Width = dc.Width; + Height = dc.Height; + } - #endregion Identifying properties + #endregion Ctor #region Basic Image Properties Left, Top, Width, Height and Opacity /// - /// Translucency of the image expressed as percentage of solidness - /// - public float Opacity { get; set; } - /// /// Width of the displayed image /// public int Width { get; set; } @@ -69,144 +53,27 @@ public class ConfigurationDefinition #endregion Basic Image Properties Left, Top, Width, Height and Opacity - #region Image cropping properties - /// - /// Starting X position of the Crop - /// - public int XOffsetStart { get; set; } - /// - /// Starting Y position of the Crop - /// - public int YOffsetStart { get; set; } - /// - /// Ending X position of the Crop - /// - public int XOffsetFinish { get; set; } - /// - /// Ending Y position of the Crop - /// - public int YOffsetFinish { get; set; } - /// - /// If true then the results of the cropping are saved - /// - public bool? SaveResults { get; set; } - #endregion Image cropping properties - - #region Public methods - - /// - /// Default constructor - /// - public ConfigurationDefinition() - { - - } - - /// - /// Copy constructor - /// - /// - public ConfigurationDefinition(ConfigurationDefinition dc) - { - Enabled = dc.Enabled; - Logger = dc.Logger; - FileName = dc.FileName; - ModuleName = dc.ModuleName; - Left = dc.Left; - Top = dc.Top; - Width = dc.Width; - Height = dc.Height; - Name = dc.Name; - XOffsetStart = dc.XOffsetStart; - XOffsetFinish = dc.XOffsetFinish; - YOffsetStart = dc.YOffsetStart; - YOffsetFinish = dc.YOffsetFinish; - SaveResults = dc.SaveResults; - Opacity = dc.Opacity; - } + #region SubConfiguration support /// - /// Crop the specified image + /// List of SubConfigurations /// - /// - /// - public BitmapSource CropImage(string imagePath) - { - if (Enabled) - { - BitmapImage src = new BitmapImage(); - src.BeginInit(); - src.UriSource = new Uri(imagePath, UriKind.Relative); - src.CacheOption = BitmapCacheOption.OnLoad; - src.EndInit(); + public List SubConfigurations { get; set; } - Int32Rect offSet = new Int32Rect(XOffsetStart, YOffsetStart, XOffsetFinish - XOffsetStart, YOffsetFinish - YOffsetStart); - CroppedBitmap croppedBitmap = new CroppedBitmap(src, offSet); - var noAlphaSource = new FormatConvertedBitmap(); - noAlphaSource.BeginInit(); - noAlphaSource.Source = croppedBitmap; - noAlphaSource.DestinationFormat = PixelFormats.Bgr24; - noAlphaSource.AlphaThreshold = 0; - noAlphaSource.EndInit(); + #endregion SubConfiguration support - if ((SaveResults ?? false) == true) - { - var fi = new FileInfo(imagePath); - - SaveImage(noAlphaSource, fi.Directory.FullName, $"X_{XOffsetStart}To{XOffsetFinish}Y_{YOffsetStart}To{YOffsetFinish}_{Opacity}"); - } - return noAlphaSource; - } - else - { - return null; - } - } + #region Protected overrides /// - /// Describes the Configuration + /// Returns the portion of the readable string specific to /// /// - public string ToReadableString() + protected override string GetReadableString() { - string completePath = null; - string fileStatus = null; - var pathExists = false; - if(!string.IsNullOrEmpty(FilePath) && Directory.Exists(FilePath) && !string.IsNullOrEmpty(FileName)) - { - completePath = Path.Combine(FilePath, FileName); - pathExists = File.Exists(completePath); - fileStatus = pathExists ? "found " : "not found "; - } - return $"Config: {Name} for: {ModuleName} at: ({Left}, {Top}) for ({Width}, {Height}) with Opacity: {Opacity} Enabled: {Enabled} from: {completePath ?? "Unknown Image"} was: {fileStatus} at Offset: ({XOffsetStart}, {YOffsetStart}) for: ({XOffsetFinish - XOffsetStart}, {YOffsetFinish - YOffsetStart})."; + return $"{Width}_{Height}"; } - /// - /// Short form - /// - /// - public override string ToString() - { - return ToReadableString(); - } - - #endregion Public methods - - #region Private helpers - - /// - /// Saves the Image in the specified format, default format is bmp - /// - /// - /// Directory to save the file to - /// Prefix to add to the filename - private void SaveImage(BitmapSource retResult, string filePath, string imagePrefix) - { - var fileName = Path.Combine(filePath, $"{imagePrefix}_{ModuleName}_{Name}_{Width}_{Height}.png"); - retResult?.SaveToPng(fileName); - Logger.Debug($"Cropped image saved as {fileName}."); - } + #endregion Protected overrides - #endregion Private helpers } } \ No newline at end of file diff --git a/MFDSettingsManager/Models/ConfigurationModelBase.cs b/MFDSettingsManager/Models/ConfigurationModelBase.cs new file mode 100644 index 0000000..e233663 --- /dev/null +++ b/MFDSettingsManager/Models/ConfigurationModelBase.cs @@ -0,0 +1,221 @@ +using log4net; +using MFDSettingsManager.Extensions; +using System; +using System.IO; +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace MFDSettingsManager.Models +{ + /// + /// Properties common to Configuration and SubConfiguration + /// + public abstract class ConfigurationModelBase + { + #region Ctor + + /// + /// Default constructor + /// + public ConfigurationModelBase() + { + + } + + /// + /// Copy constructor + /// + /// + public ConfigurationModelBase(ConfigurationModelBase cb) + { + Enabled = cb.Enabled; + Logger = cb.Logger; + FileName = cb.FileName; + ModuleName = cb.ModuleName; + Name = cb.Name; + XOffsetStart = cb.XOffsetStart; + XOffsetFinish = cb.XOffsetFinish; + YOffsetStart = cb.YOffsetStart; + YOffsetFinish = cb.YOffsetFinish; + Opacity = cb.Opacity; + } + + #endregion Ctor + + #region Utility properties + + /// + /// Logger + /// + public ILog Logger { get; set; } + + /// + /// Folder used to cache the generated images + /// + public string CacheFolder => GetCacheFolderForModule(); + + #endregion Utility properties + + #region Identifying properties + + /// + /// Module Name + /// + public string ModuleName { get; set; } + /// + /// Name of the Configuration + /// + public string Name { get; set; } + /// + /// FileName for the image cropping that this configuration uses + /// + public string FileName { get; set; } + + /// + /// The starting file path for the configuration + /// + public string FilePath { get; set; } + + /// + /// Determines if the configuration is rendered + /// + public bool Enabled { get; internal set; } + + /// + /// Default readable string + /// + /// + protected virtual string GetReadableString() + { + return ""; + } + + #endregion Identifying properties + + #region Image cropping properties + + /// + /// Translucency of the image expressed as percentage of solidness + /// + public float Opacity { get; set; } + /// + /// Starting X position of the Crop + /// + public int XOffsetStart { get; set; } + /// + /// Starting Y position of the Crop + /// + public int YOffsetStart { get; set; } + /// + /// Ending X position of the Crop + /// + public int XOffsetFinish { get; set; } + /// + /// Ending Y position of the Crop + /// + public int YOffsetFinish { get; set; } + + #endregion Image cropping properties + + #region Image cropping + + /// + /// Crop the specified image + /// + /// + /// + public virtual BitmapSource CropImage(string imagePath) + { + if (Enabled) + { + BitmapImage src = new BitmapImage(); + src.BeginInit(); + src.UriSource = new Uri(imagePath, UriKind.Relative); + src.CacheOption = BitmapCacheOption.OnLoad; + src.EndInit(); + + Int32Rect offSet = new Int32Rect(XOffsetStart, YOffsetStart, XOffsetFinish - XOffsetStart, YOffsetFinish - YOffsetStart); + CroppedBitmap croppedBitmap = new CroppedBitmap(src, offSet); + var noAlphaSource = new FormatConvertedBitmap(); + noAlphaSource.BeginInit(); + noAlphaSource.Source = croppedBitmap; + noAlphaSource.DestinationFormat = PixelFormats.Bgr24; + noAlphaSource.AlphaThreshold = 0; + noAlphaSource.EndInit(); + SaveImage(noAlphaSource, CacheFolder, $"X_{XOffsetStart}To{XOffsetFinish}Y_{YOffsetStart}To{YOffsetFinish}_{Opacity}"); + return noAlphaSource; + } + else + { + return null; + } + } + + #endregion Image cropping + + #region Image saving + + /// + /// Saves the Image in the specified format, default format is bmp + /// + /// + /// Directory to save the file to + /// Prefix to add to the filename + protected virtual void SaveImage(BitmapSource retResult, string filePath, string imagePrefix) + { + Directory.CreateDirectory(filePath); + var fileName = Path.Combine(filePath, $"{imagePrefix}_{Name}_{GetReadableString()}.png"); + retResult?.SaveToPng(fileName); + Logger.Info($"Cropped image saved as {fileName}."); + } + + + #endregion Image saving + + #region Public overrides + + /// + /// Describes the Configuration + /// + /// + public string ToReadableString() + { + string completePath = null; + string fileStatus = null; + var pathExists = false; + if (!string.IsNullOrEmpty(FilePath) && Directory.Exists(FilePath) && !string.IsNullOrEmpty(FileName)) + { + completePath = Path.Combine(FilePath, FileName); + pathExists = File.Exists(completePath); + fileStatus = pathExists ? "found " : "not found "; + } + + return $"Config: {Name} for: {ModuleName} at: {GetReadableString()} with Opacity: {Opacity} Enabled: {Enabled} from: {completePath ?? "Unknown Image"} was: {fileStatus} at Offset: ({XOffsetStart}, {YOffsetStart}) for: ({XOffsetFinish - XOffsetStart}, {YOffsetFinish - YOffsetStart})."; + } + + /// + /// Short form + /// + /// + public override string ToString() + { + return ToReadableString(); + } + + #endregion Public overrides + + #region Private helpers + + /// + /// Returns the location of the Cache for the current Module + /// + /// + private string GetCacheFolderForModule() + { + return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), $"Vyper Industries\\MFD4CTS\\cache\\{ModuleName}"); + } + + #endregion Private helpers + } +} diff --git a/MFDSettingsManager/Models/SubConfigurationDefinition.cs b/MFDSettingsManager/Models/SubConfigurationDefinition.cs new file mode 100644 index 0000000..b6142bc --- /dev/null +++ b/MFDSettingsManager/Models/SubConfigurationDefinition.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; + +namespace MFDSettingsManager.Models +{ + /// + /// Defines a SubConfiguration + /// + public class SubConfigurationDefinition : ConfigurationModelBase + { + #region Ctor + + /// + /// Default constructor + /// + public SubConfigurationDefinition() + { + + } + + /// + /// Copy constructor + /// + /// + public SubConfigurationDefinition(SubConfigurationDefinition dc) : base(dc) + { + StartX = dc.StartX; + EndX = dc.EndX; + StartY = dc.StartY; + EndY = dc.EndY; + } + + #endregion Ctor + + #region Basic Image Properties StartX, EndX, StartY and EndY + + /// + /// The X coordinate inside of the Configuration image relative to (0,0) to start rendering the image + /// + public int StartX { get; set; } + /// + /// The X coordinate inside of the Configuration image relative to (0,0) to end rendering the image + /// + public int EndX { get; set; } + /// + /// The Y coordinate inside of the Configuration image relative to (0,0) to start rendering the image + /// + public int StartY { get; set; } + /// + /// The Y coordinate inside of the Configuration image relative to (0,0) to end rendering the image + /// + public int EndY { get; set; } + + #endregion Basic Image Properties StartX, EndX, StartY and EndY + + #region Protected overrides + + /// + /// Returns the portion of the readable string specific to + /// + /// + + protected override string GetReadableString() + { + return $"{EndX - StartX}_{EndY - StartY}"; + } + + #endregion Protected overrides + } +} \ No newline at end of file diff --git a/MFDSettingsManager/Properties/AssemblyInfo.cs b/MFDSettingsManager/Properties/AssemblyInfo.cs index 1a7625e..a699024 100644 --- a/MFDSettingsManager/Properties/AssemblyInfo.cs +++ b/MFDSettingsManager/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.5.0.0")] -[assembly: AssemblyFileVersion("2.5.0.0")] +[assembly: AssemblyVersion("2.6.1.0")] +[assembly: AssemblyFileVersion("2.6.1.0")] diff --git a/MFDisplay.sln b/MFDisplay.sln index 2ae6ac0..4d0656f 100644 --- a/MFDisplay.sln +++ b/MFDisplay.sln @@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{EC07B551-2 ProjectSection(SolutionItems) = preProject mfdisp_exe_test.tmc = mfdisp_exe_test.tmc MFDisplay\Docs\testfunction.tmc = MFDisplay\Docs\testfunction.tmc + ..\..\..\Downloads\tv-test-pattern-146649_960_720.png = ..\..\..\Downloads\tv-test-pattern-146649_960_720.png EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MFDSettingsManager", "MFDSettingsManager\MFDSettingsManager.csproj", "{BB12C431-7568-4AB3-AC21-4D6396744F22}" diff --git a/MFDisplay/App.config b/MFDisplay/App.config index c0cfb9c..44abfaf 100644 --- a/MFDisplay/App.config +++ b/MFDisplay/App.config @@ -7,9 +7,34 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MFDisplay/AuxWindow.xaml b/MFDisplay/AuxWindow.xaml index b9871a2..608a9fe 100644 --- a/MFDisplay/AuxWindow.xaml +++ b/MFDisplay/AuxWindow.xaml @@ -7,6 +7,7 @@ mc:Ignorable="d" Title="MFD" Name="auxWindow" BorderThickness="0" Topmost="True" Loaded="Window_Loaded" Closed="Window_Closed" ResizeMode="NoResize" WindowStyle="None" ShowInTaskbar="False" Opacity="0" AllowsTransparency="True"> - + + diff --git a/MFDisplay/AuxWindow.xaml.cs b/MFDisplay/AuxWindow.xaml.cs index 8bac1fb..67bc707 100644 --- a/MFDisplay/AuxWindow.xaml.cs +++ b/MFDisplay/AuxWindow.xaml.cs @@ -2,6 +2,7 @@ using MFDSettingsManager.Models; using System; using System.IO; +using System.Linq; using System.Windows; using System.Windows.Media.Imaging; using Path = System.IO.Path; @@ -18,6 +19,11 @@ public partial class AuxWindow : Window /// public bool IsWindowLoaded { get; protected set; } + /// + /// The name of the sub configuration to load + /// + public string SubConfigurationName { get; set; } + /// /// MFD Configuration /// @@ -84,9 +90,15 @@ private void Window_Loaded(object sender, RoutedEventArgs e) Close(); return; } - - LoadImage(); - Logger?.Debug($"Loading the configuration for {Configuration.Name} from Module {Configuration.ModuleName}"); + if (Configuration.Enabled) + { + LoadImage(); + Logger?.Debug($"Loading the configuration for {Configuration.Name} from Module {Configuration.ModuleName}"); + } + else + { + Logger?.Info($"Configuration for {Configuration.Name} for Module {Configuration.ModuleName} is currently disabled in configuration."); + } } /// @@ -94,7 +106,7 @@ private void Window_Loaded(object sender, RoutedEventArgs e) /// public void LoadImage() { - BitmapSource bitmapSource = null; + SubConfigurationDefinition subConfig = null; IsWindowLoaded = false; if (!IsValid) { @@ -103,34 +115,99 @@ public void LoadImage() } else { - var filePath = Path.Combine(FilePath, Configuration.FileName); + var cacheFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), $"Vyper Industries\\MFD4CTS\\cache\\{Configuration.ModuleName}"); + + // Previous renders are cached so if the cache file is available then it will be used + var imagePrefix = $"X_{Configuration.XOffsetStart}To{Configuration.XOffsetFinish}Y_{Configuration.YOffsetStart}To{Configuration.YOffsetFinish}_{Configuration.Opacity}"; + var cacheFile = Path.Combine(cacheFolder, $"{imagePrefix}_{Configuration.Name}_{Configuration.Width}_{Configuration.Height}.png"); + imgMain.Source = GetBitMapSource(Configuration, cacheFolder, cacheFile); imgMain.Width = Width; imgMain.Height = Height; + imgMain.Visibility = Visibility.Visible; + try { - bitmapSource = Configuration.CropImage(filePath); + // First check to see if we are using a SubConfiguration + if (!string.IsNullOrEmpty(SubConfigurationName)) + { + subConfig = Configuration?.SubConfigurations?.FirstOrDefault(sc => sc.Name.Equals(SubConfigurationName, StringComparison.InvariantCultureIgnoreCase)); + if (subConfig != null) + { + Logger?.Info($"Processing sub-configuration: {subConfig.ToString()} for Module: {Configuration.ModuleName}!"); + var insetImagePrefix = $"X_{subConfig.XOffsetStart}To{subConfig.XOffsetFinish}Y_{subConfig.YOffsetStart}To{subConfig.YOffsetFinish}_{subConfig.Opacity}"; + var width = subConfig.EndX - subConfig.StartX; + var height = subConfig.EndY - subConfig.StartY; + var insetCacheFile = Path.Combine(cacheFolder, $"{insetImagePrefix}_{subConfig.Name}_{width}_{height}.png"); + imgInsert.Source = GetBitMapSource(subConfig, cacheFolder, insetCacheFile); + imgInsert.Width = width; + imgInsert.Height = height; + imgInsert.Opacity = subConfig.Opacity; + imgInsert.Visibility = Visibility.Visible; + } + } } catch (Exception ex) { - Logger?.Error($"Unable to load {Configuration.ToReadableString()}.", ex); + Logger?.Error($"Unable to load {subConfig?.ToReadableString()}.", ex); Close(); } - finally + IsWindowLoaded = true; + Visibility = Visibility.Visible; + } + } + + /// + /// Loads the image from the cache or crops it from the source image + /// + /// Must be derived from + /// The configuration source, derived from + /// Location of the cache of images + /// Full path to the requested file in the cache + /// + private BitmapSource GetBitMapSource(T configSource, string cacheFolder, string cacheFile) + where T: ConfigurationModelBase + { + BitmapSource bitmapSource = null; + string filePath = string.Empty; + + try + { + if (File.Exists(cacheFile)) + { + Logger.Info($"Cache file found: {cacheFile}"); + Stream imageStreamSource = new FileStream(cacheFile, FileMode.Open, FileAccess.Read, FileShare.Read); + PngBitmapDecoder decoder = new PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); + bitmapSource = decoder.Frames[0]; + } + else { - if(bitmapSource != null) - { - imgMain.Source = bitmapSource; - IsWindowLoaded = true; - Logger?.Debug($"Image {filePath} is loaded."); - Visibility = Visibility.Visible; - } - else + if (!Directory.Exists(cacheFolder)) { - Logger?.Warn($"Configuration was not loaded -> {Configuration.ToReadableString()}."); - Close(); + Directory.CreateDirectory(cacheFolder); } + filePath = Path.Combine(FilePath, configSource.FileName); + bitmapSource = configSource.CropImage(filePath); } } + catch (Exception ex) + { + Logger?.Error($"Unable to load {configSource.ToReadableString()}.", ex); + Close(); + } + finally + { + if (bitmapSource != null) + { + Logger?.Info($"Configuration {configSource.ToReadableString()} is loaded."); + } + else + { + Logger?.Warn($"Configuration was not loaded -> {configSource.ToReadableString()}."); + Close(); + } + } + + return bitmapSource; } private void Window_Closed(object sender, EventArgs e) diff --git a/MFDisplay/MFDisplay.csproj b/MFDisplay/MFDisplay.csproj index f1f645c..b46efff 100644 --- a/MFDisplay/MFDisplay.csproj +++ b/MFDisplay/MFDisplay.csproj @@ -286,6 +286,10 @@ Settings.settings True + + Always + Designer + @@ -301,13 +305,8 @@ Designer Always - - Designer - Always - - Designer Always diff --git a/MFDisplay/MFDisplay.csproj.user b/MFDisplay/MFDisplay.csproj.user index 7a55b2a..9c9b0c0 100644 --- a/MFDisplay/MFDisplay.csproj.user +++ b/MFDisplay/MFDisplay.csproj.user @@ -9,12 +9,12 @@ en-US false + ShowAllFiles false - - + -mod F-14R -submod SPL \ No newline at end of file diff --git a/MFDisplay/MFDisplayApp.xaml.cs b/MFDisplay/MFDisplayApp.xaml.cs index cf40be7..6896f7f 100644 --- a/MFDisplay/MFDisplayApp.xaml.cs +++ b/MFDisplay/MFDisplayApp.xaml.cs @@ -21,6 +21,8 @@ public partial class MFDisplayApp : Application, ISingleInstanceApp private const string Company = "Vyper Industries"; private const string Years = "2018, 2019"; + static string ConfigurationPath { get; set; } + /// /// Main entry point /// @@ -49,11 +51,20 @@ public static void Main() public bool SignalExternalCommandLineArgs(IList args) { var modSpecified = args.GetSafeArgumentFrom("-mod"); + var subModeSpecified = args.GetSafeArgumentFrom("-submod"); if(!string.IsNullOrEmpty(modSpecified)) { Logger.Info($"External request to change module to {modSpecified}."); ((MainWindow)MainWindow).ChangeSelectedModule(modSpecified); } + + if (!string.IsNullOrEmpty(subModeSpecified)) + { + Logger.Info($"External request to change sub-module to {subModeSpecified}."); + ((MainWindow)MainWindow).ChangeSelectedSubModule(subModeSpecified); + } + + return true; } @@ -79,15 +90,13 @@ private string GetVersionString() private ILog Logger; private static readonly bool configPresent = true; - private static readonly string configurationFile = ""; static MFDisplayApp() { - var exeAssem = Assembly.GetExecutingAssembly(); - configurationFile = $"{exeAssem.Location}.config"; - if (!File.Exists(configurationFile)) + ConfigurationPath = $"{Assembly.GetExecutingAssembly().Location}.config"; + if (!File.Exists(ConfigurationPath)) { - MessageBox.Show($"The configuration file could not be found! Please re-install or repair the application or restore the configuration file {configurationFile}.", "Invalid Configuration", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show($"The configuration file could not be found! Please re-install or repair the application or restore the configuration file {ConfigurationPath}.", "Invalid Configuration", MessageBoxButton.OK, MessageBoxImage.Error); configPresent = false; return; } @@ -104,11 +113,11 @@ internal void ShowConfigurationError(Window parent = null) var logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Vyper Industries\MFD4CTS\status.log"); if(parent != null) { - MessageBox.Show(parent, $"Unable to load the configuration. Please check the log at {logPath} for details.", "Error in Configuration", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show(parent, $"Unable to load the configuration from {ConfigurationPath}. Please check the log at {logPath} for details.", "Error in Configuration", MessageBoxButton.OK, MessageBoxImage.Error); } else { - MessageBox.Show($"Unable to load the configuration. Please check the log at {logPath} for details.", "Error in Configuration", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBox.Show($"Unable to load the configuration from {ConfigurationPath}. Please check the log at {logPath} for details.", "Error in Configuration", MessageBoxButton.OK, MessageBoxImage.Error); } } @@ -120,6 +129,7 @@ internal void ShowConfigurationError(Window parent = null) protected override void OnStartup(StartupEventArgs e) { var modSpecified = e.Args.GetSafeArgumentFrom("-mod"); + var subModeSpecified = e.Args.GetSafeArgumentFrom("-submod"); if (!configPresent) { @@ -128,8 +138,7 @@ protected override void OnStartup(StartupEventArgs e) } Logger = LogManager.GetLogger("MFD4CTS"); - var assmLocation = Assembly.GetExecutingAssembly().Location; - var sectionConfig = MFDConfigurationSection.GetConfig(Logger); + var sectionConfig = MFDConfigurationSection.GetConfig(Logger, ConfigurationPath); if(sectionConfig == null) { @@ -139,28 +148,18 @@ protected override void OnStartup(StartupEventArgs e) } Configuration = sectionConfig.ToModel(Logger); - if(!Directory.Exists(Configuration?.FilePath)) - { - var mfdSettingsFile = Path.Combine((new FileInfo(assmLocation))?.DirectoryName, "mfdsettings.config"); - var errorMessage = $"{Configuration.FilePath} is not a valid path. Please use an elevated editor, runas Administrator, and edit the FilePath in the file {mfdSettingsFile}"; - Logger.Error(errorMessage); - MessageBox.Show(errorMessage, "Configuration Error", MessageBoxButton.OK, MessageBoxImage.Error); - Shutdown(2); - } - else + Logger.Info($"Startup"); + var mainWindow = new MainWindow() { - Logger.Info($"Startup"); - var mainWindow = new MainWindow() - { - Config = Configuration, - Logger = Logger, - WindowState = WindowState.Minimized, - PassedModule = string.IsNullOrEmpty(modSpecified) ? null : modSpecified - }; - - mainWindow.ShowDialog(); - Shutdown(0); - } + Config = Configuration, + Logger = Logger, + WindowState = WindowState.Minimized, + PassedModule = string.IsNullOrEmpty(modSpecified) ? null : modSpecified, + PassedSubModule = string.IsNullOrEmpty(subModeSpecified) ? null : subModeSpecified, + }; + + mainWindow.ShowDialog(); + Shutdown(0); base.OnStartup(e); } diff --git a/MFDisplay/MainWindow.xaml b/MFDisplay/MainWindow.xaml index dadf1f1..1568a10 100644 --- a/MFDisplay/MainWindow.xaml +++ b/MFDisplay/MainWindow.xaml @@ -12,6 +12,9 @@ + + + diff --git a/MFDisplay/MainWindow.xaml.cs b/MFDisplay/MainWindow.xaml.cs index dae4d76..89c56fe 100644 --- a/MFDisplay/MainWindow.xaml.cs +++ b/MFDisplay/MainWindow.xaml.cs @@ -2,6 +2,7 @@ using MFDSettingsManager.Models; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Windows; using System.Windows.Controls; @@ -43,6 +44,11 @@ public partial class MainWindow : Window /// public string PassedModule { get; internal set; } + /// + /// The name of the sub-module that was passed + /// + public string PassedSubModule { get; internal set; } + /// /// Ctor, initializes component, logging, sorted list and loads the configuration /// @@ -101,7 +107,8 @@ public void CreateWindows() { Logger = Logger, Configuration = config, - FilePath = Config.FilePath + FilePath = Config.FilePath, + SubConfigurationName = PassedSubModule }; newAuxWindow.Show(); if (newAuxWindow.IsWindowLoaded) @@ -145,6 +152,18 @@ public void ChangeSelectedModule(string moduleName) } } + /// + /// Changes the selected sub-module + /// + /// + public void ChangeSelectedSubModule(string subModeSpecified) + { + PassedSubModule = subModeSpecified; + DestroyWindows(); + CreateWindows(); + } + + private void ProcessChangedModule(string moduleName) { if (GetSelectedDefinition(moduleName)) @@ -230,5 +249,30 @@ private void FileMenuItem_Click(object sender, RoutedEventArgs e) { Close(); } + + /// + /// Clears the cache of all PNG files + /// + /// + /// + private void ClearCache_Click(object sender, RoutedEventArgs e) + { + DestroyWindows(); + var cacheFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), $"Vyper Industries\\MFD4CTS\\cache\\"); + var cacheParent = new DirectoryInfo(cacheFolder); + var fileList = cacheParent.EnumerateFiles("*.png", SearchOption.AllDirectories).ToList(); + fileList.ForEach((file) => + { + try + { + File.Delete(file.FullName); + } + catch (System.Exception ex) + { + Logger.Warn($"Unable to delete cache file: {file.FullName}"); + } + }); + CreateWindows(); + } } } diff --git a/MFDisplay/Properties/AssemblyInfo.cs b/MFDisplay/Properties/AssemblyInfo.cs index e4a4201..e866637 100644 --- a/MFDisplay/Properties/AssemblyInfo.cs +++ b/MFDisplay/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.5.0.0")] -[assembly: AssemblyFileVersion("2.5.0.0")] +[assembly: AssemblyVersion("2.6.1.0")] +[assembly: AssemblyFileVersion("2.6.1.0")] diff --git a/MFDisplay/log4net.config b/MFDisplay/log4net.config deleted file mode 100644 index f920a1c..0000000 --- a/MFDisplay/log4net.config +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MFDisplay/mfdsettings.config b/MFDisplay/mfdsettings.config index 8bbd34f..d4ae970 100644 --- a/MFDisplay/mfdsettings.config +++ b/MFDisplay/mfdsettings.config @@ -13,11 +13,9 @@ https://github.com/ScottyMac52/MFDisplay/wiki/Configuration-Guide --> - - + + - + @@ -173,7 +171,17 @@ - + + + + + + + + + + + @@ -184,6 +192,16 @@ + + + + + + + + + + diff --git a/MFDisplay/mfdsettings.xsd b/MFDisplay/mfdsettings.xsd index c59a23c..ed30681 100644 --- a/MFDisplay/mfdsettings.xsd +++ b/MFDisplay/mfdsettings.xsd @@ -4,11 +4,10 @@ attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> - + + - Configuration defines all properties required to crop and image, re-size it and display it on the screen. The image is derived from the image filename specified either by the Module or by the configuration itself. + BaseConfiguration defines inserts of cropped images onto a Configuration. Opacity of the image as rendered on the screen expressed as a percentage of 1. 30% Opacity is .3. - - - Width of the image in screen pixels. - - - - - Height of the image in screen pixels. - - - - - Left position of the image in screen pixels. - - - - - Top position of the image in screen pixels. - - + + + Configuration defines all properties required to crop and image, re-size it and display it on the screen. The image is derived from the image filename specified either by the Module or by the configuration itself. + + + + + + Width of the image in screen pixels. + + + + + Height of the image in screen pixels. + + + + + Left position of the image in screen pixels. + + + + + Top position of the image in screen pixels. + + + + + + + + SubConfiguration defines the image that gets cropped and pled inside a Configuration. + + + + + + Starting X coordinate relative to (0,0) of the Configuration where the image is rendered. + + + + + Ending X coordinate relative to (0,0) of the Configuration where the image is rendered. + + + + + Starting Y coordinate relative to (0,0) of the Configuration where the image is rendered. + + + + + Ending Y coordinate relative to (0,0) of the Configuration where the image is rendered. + + + + + Defines a module configuration. The moduleName, displayName and filename @@ -124,11 +177,34 @@ maxOccurs="unbounded" nillable="true"> - Module configuration. + Configuration for a Module. - + + + + + SubConfigurations for the current Configuration + + + + + + SubConfiguration for a Configuration. + + + + + + + + + + + + + @@ -171,9 +247,6 @@ - - WHere does this appear in schema? - + + Configured Modules + + + Module Configuration + @@ -212,13 +291,6 @@ - - - If true then PNG images of the cropped configurations are saved in the save directory they originated from in the following format: - - diff --git a/MFDisplay/test.config b/MFDisplay/test.config new file mode 100644 index 0000000..145f5e9 --- /dev/null +++ b/MFDisplay/test.config @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Setup/Setup.vdproj b/Setup/Setup.vdproj index f44b11d..23f9143 100644 --- a/Setup/Setup.vdproj +++ b/Setup/Setup.vdproj @@ -3472,7 +3472,7 @@ { "AssemblyRegister" = "3:1" "AssemblyIsInGAC" = "11:FALSE" - "AssemblyAsmDisplayName" = "8:MFDSettingsManager, Version=2.5.0.0, Culture=neutral, processorArchitecture=x86" + "AssemblyAsmDisplayName" = "8:MFDSettingsManager, Version=2.6.1.0, Culture=neutral, processorArchitecture=x86" "ScatterAssemblies" { "_C4DC3EF2B28BD12B944CD4F281C1AE06" @@ -4075,15 +4075,15 @@ { "Name" = "8:Microsoft Visual Studio" "ProductName" = "8:MFD4CTS" - "ProductCode" = "8:{C947D7A5-4E57-4FE0-9B29-5B9CD8E7E7DD}" - "PackageCode" = "8:{817B5322-4A89-4B05-AC11-5081F11AD84E}" + "ProductCode" = "8:{394A03CA-2021-4C58-AB25-6AD614E510CA}" + "PackageCode" = "8:{A9424981-83B2-425E-9810-2BD624E175D7}" "UpgradeCode" = "8:{684D58BF-80C4-4679-8A57-A5856787407F}" "AspNetVersion" = "8:4.0.30319.0" "RestartWWWService" = "11:FALSE" "RemovePreviousVersions" = "11:FALSE" "DetectNewerInstalledVersion" = "11:TRUE" "InstallAllUsers" = "11:TRUE" - "ProductVersion" = "8:2.5.0" + "ProductVersion" = "8:2.6.1" "Manufacturer" = "8:Vyper Industries" "ARPHELPTELEPHONE" = "8:" "ARPHELPLINK" = "8:https://github.com/ScottyMac52/MFDisplay/issues"