diff --git a/src/HUDMerger.Core/App.cs b/src/HUDMerger.Core/App.cs new file mode 100644 index 0000000..b3aaa50 --- /dev/null +++ b/src/HUDMerger.Core/App.cs @@ -0,0 +1,10 @@ +using System; +using System.Text.RegularExpressions; + +namespace HUDMerger.Core; + +public partial class App +{ + [GeneratedRegex(@"[/\\]+", RegexOptions.Compiled)] + public static partial Regex PathSeparatorRegex(); +} diff --git a/src/HUDMerger/Commands/CommandBase.cs b/src/HUDMerger.Core/Commands/CommandBase.cs similarity index 94% rename from src/HUDMerger/Commands/CommandBase.cs rename to src/HUDMerger.Core/Commands/CommandBase.cs index 8d24d2b..1ed2c1a 100644 --- a/src/HUDMerger/Commands/CommandBase.cs +++ b/src/HUDMerger.Core/Commands/CommandBase.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Input; -namespace HUDMerger.Commands; +namespace HUDMerger.Core.Commands; public abstract class CommandBase : ICommand, IDisposable { diff --git a/src/HUDMerger/Commands/MergeCommand.cs b/src/HUDMerger.Core/Commands/MergeCommand.cs similarity index 72% rename from src/HUDMerger/Commands/MergeCommand.cs rename to src/HUDMerger.Core/Commands/MergeCommand.cs index 3a88718..b8bd243 100644 --- a/src/HUDMerger/Commands/MergeCommand.cs +++ b/src/HUDMerger.Core/Commands/MergeCommand.cs @@ -4,20 +4,25 @@ using System.IO; using System.Linq; using System.Windows; -using HUDMerger.Models; -using HUDMerger.ViewModels; +using HUDMerger.Core.Models; +using HUDMerger.Core.Services; +using HUDMerger.Core.ViewModels; -namespace HUDMerger.Commands; +namespace HUDMerger.Core.Commands; public class MergeCommand : CommandBase { private bool _disposed; private readonly MainWindowViewModel _mainWindowViewModel; + private readonly ISettingsService SettingsService; + private readonly IMessageBoxService MessageBoxService; - public MergeCommand(MainWindowViewModel mainWindowViewModel) + public MergeCommand(MainWindowViewModel mainWindowViewModel, ISettingsService settingsService, IMessageBoxService messageBoxService) { _mainWindowViewModel = mainWindowViewModel; _mainWindowViewModel.PropertyChanged += _mainWindowViewModel_PropertyChanged; + SettingsService = settingsService; + MessageBoxService = messageBoxService; } private void _mainWindowViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e) @@ -44,7 +49,7 @@ static bool PathContainsPath(string parentDir, string subDir) return !relativeDirectory.StartsWith("..") && !Path.IsPathRooted(relativeDirectory); } - bool teamFortress2FolderContainsTarget = PathContainsPath(Path.Join(((App)Application.Current).Settings.Value.TeamFortress2Folder, "tf\\custom"), _mainWindowViewModel.TargetHUD!.FolderPath); + bool teamFortress2FolderContainsTarget = PathContainsPath(Path.Join(SettingsService.Settings.TeamFortress2Folder, "tf\\custom"), _mainWindowViewModel.TargetHUD!.FolderPath); Process[] processes; @@ -63,7 +68,7 @@ static bool PathContainsPath(string parentDir, string subDir) if (teamFortress2FolderContainsTarget && processes.Length != 0) { - MessageBox.Show("TF2 process open, cannot merge!", "TF2 Open Error", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBoxService.ShowException(new Exception("TF2 process open, cannot merge!"), "TF2 Open Error"); return; } #endif @@ -74,14 +79,15 @@ static bool PathContainsPath(string parentDir, string subDir) _mainWindowViewModel.HUDPanelViewModels .Where((hudPanelViewModel) => hudPanelViewModel.Selected) .Select((hudPanelViewModel) => hudPanelViewModel.HUDPanel) - .ToArray() + .ToArray(), + SettingsService ); - MessageBox.Show("Done!"); + MessageBoxService.Show("Done!"); } catch (Exception e) { - MessageBox.Show(e.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + MessageBoxService.ShowException(e, "Error"); } } diff --git a/src/HUDMerger/Exceptions/FileException.cs b/src/HUDMerger.Core/Exceptions/FileException.cs similarity index 80% rename from src/HUDMerger/Exceptions/FileException.cs rename to src/HUDMerger.Core/Exceptions/FileException.cs index a220869..134038b 100644 --- a/src/HUDMerger/Exceptions/FileException.cs +++ b/src/HUDMerger.Core/Exceptions/FileException.cs @@ -1,8 +1,8 @@ using System; -using HUDMerger.Models; +using HUDMerger.Core.Models; using VDF.Exceptions; -namespace HUDMerger.Exceptions; +namespace HUDMerger.Core.Exceptions; public class FileException(HUD hud, string relativePath, VDFSyntaxException innerException) : Exception($"{hud.Name}: {App.PathSeparatorRegex().Replace(relativePath, "/")}: {innerException.Message}") { diff --git a/src/HUDMerger/Extensions/BinaryReaderExtensions.cs b/src/HUDMerger.Core/Extensions/BinaryReaderExtensions.cs similarity index 90% rename from src/HUDMerger/Extensions/BinaryReaderExtensions.cs rename to src/HUDMerger.Core/Extensions/BinaryReaderExtensions.cs index 975fe4f..e686117 100644 --- a/src/HUDMerger/Extensions/BinaryReaderExtensions.cs +++ b/src/HUDMerger.Core/Extensions/BinaryReaderExtensions.cs @@ -3,7 +3,7 @@ using System.IO; using System.Text; -namespace HUDMerger.Extensions; +namespace HUDMerger.Core.Extensions; public static class BinaryReaderExtensions { diff --git a/src/HUDMerger/Extensions/HashSetExtensions.cs b/src/HUDMerger.Core/Extensions/HashSetExtensions.cs similarity index 95% rename from src/HUDMerger/Extensions/HashSetExtensions.cs rename to src/HUDMerger.Core/Extensions/HashSetExtensions.cs index 98bb0da..f2d4211 100644 --- a/src/HUDMerger/Extensions/HashSetExtensions.cs +++ b/src/HUDMerger.Core/Extensions/HashSetExtensions.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using VDF.Models; -namespace HUDMerger.Extensions; +namespace HUDMerger.Core.Extensions; public static class HashSetExtensions { diff --git a/src/HUDMerger/Extensions/KeyValuesExtensions.cs b/src/HUDMerger.Core/Extensions/KeyValuesExtensions.cs similarity index 98% rename from src/HUDMerger/Extensions/KeyValuesExtensions.cs rename to src/HUDMerger.Core/Extensions/KeyValuesExtensions.cs index 667d66c..4d5999c 100644 --- a/src/HUDMerger/Extensions/KeyValuesExtensions.cs +++ b/src/HUDMerger.Core/Extensions/KeyValuesExtensions.cs @@ -4,7 +4,7 @@ using VDF; using VDF.Models; -namespace HUDMerger.Extensions; +namespace HUDMerger.Core.Extensions; public static class KeyValuesExtensions { diff --git a/src/HUDMerger.Core/HUDMerger.Core.csproj b/src/HUDMerger.Core/HUDMerger.Core.csproj new file mode 100644 index 0000000..b904748 --- /dev/null +++ b/src/HUDMerger.Core/HUDMerger.Core.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + HUDMerger.Core + enable + + + + + + + + + + + + + + Always + + + + diff --git a/src/HUDMerger/Models/Dependencies.cs b/src/HUDMerger.Core/Models/Dependencies.cs similarity index 97% rename from src/HUDMerger/Models/Dependencies.cs rename to src/HUDMerger.Core/Models/Dependencies.cs index fe620c1..1eb664b 100644 --- a/src/HUDMerger/Models/Dependencies.cs +++ b/src/HUDMerger.Core/Models/Dependencies.cs @@ -3,12 +3,12 @@ using System.IO; using System.Linq; using System.Text.Json; -using HUDMerger.Extensions; -using HUDMerger.Services; +using HUDMerger.Core.Extensions; +using HUDMerger.Core.Services; using VDF; using VDF.Models; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; public class Dependencies { diff --git a/src/HUDMerger/Models/FilesHashSet.cs b/src/HUDMerger.Core/Models/FilesHashSet.cs similarity index 96% rename from src/HUDMerger/Models/FilesHashSet.cs rename to src/HUDMerger.Core/Models/FilesHashSet.cs index 2372b0c..b300dd9 100644 --- a/src/HUDMerger/Models/FilesHashSet.cs +++ b/src/HUDMerger.Core/Models/FilesHashSet.cs @@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; public class FilesHashSet : HashSet { diff --git a/src/HUDMerger/Models/HUD.cs b/src/HUDMerger.Core/Models/HUD.cs similarity index 96% rename from src/HUDMerger/Models/HUD.cs rename to src/HUDMerger.Core/Models/HUD.cs index b51fc2b..0433304 100644 --- a/src/HUDMerger/Models/HUD.cs +++ b/src/HUDMerger.Core/Models/HUD.cs @@ -8,14 +8,14 @@ using System.Windows; using HUDAnimations.Models; using HUDAnimations.Models.Animations; -using HUDMerger.Exceptions; -using HUDMerger.Extensions; -using HUDMerger.Models.Scheme; -using HUDMerger.Services; +using HUDMerger.Core.Exceptions; +using HUDMerger.Core.Extensions; +using HUDMerger.Core.Models.Scheme; +using HUDMerger.Core.Services; using VDF; using VDF.Models; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; /// /// Represents a custom HUD @@ -118,7 +118,7 @@ bool TestKeyValues(KeyValues keyValues) /// HUD to merge panels from /// HUD to merge panels to /// Panels - public static void Merge(HUD source, HUD target, HUDPanel[] panels) + public static void Merge(HUD source, HUD target, HUDPanel[] panels, ISettingsService settingsService) { Dependencies dependencies = new(panels.Select((panel) => panel.Dependencies).OfType()); dependencies.Files.UnionWith(panels.Select((panel) => panel.Main).Where((main) => !string.IsNullOrEmpty(main))); @@ -129,9 +129,9 @@ public static void Merge(HUD source, HUD target, HUDPanel[] panels) .SelectMany((files) => files) ); - IHUDFileReaderService reader = new HUDFileReaderService(); + IHUDFileReaderService reader = new HUDFileReaderService(settingsService); - Func?>[] actions = + Func?>[] actions = [ AddDependencies, MergeHUDLayout, @@ -149,11 +149,11 @@ public static void Merge(HUD source, HUD target, HUDPanel[] panels) List> commitActions = []; List exceptions = []; - foreach (Func?> action in actions) + foreach (Func?> action in actions) { try { - Action? result = action(reader, source, target, dependencies); + Action? result = action(reader, source, target, dependencies, settingsService); if (result != null) { commitActions.Add(result); @@ -186,13 +186,13 @@ public static void Merge(HUD source, HUD target, HUDPanel[] panels) } } - private static Action? AddDependencies(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? AddDependencies(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { dependencies.Add(reader, source); return null; } - private static Action? MergeHUDLayout(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergeHUDLayout(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { if (dependencies.HUDLayout.Count == 0) { @@ -377,7 +377,7 @@ void RemoveBaseHUDLayoutEntries(string folderPath, IEnumerable baseFiles }; } - private static Action? MergeHUDAnimations(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergeHUDAnimations(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { if (dependencies.Events.Count == 0) { @@ -503,7 +503,7 @@ bool SourceHUDAnimationsFileExists(KeyValue kv) }; } - private static Action? MergeClientScheme(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergeClientScheme(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { if (!dependencies.ClientScheme.Any()) { @@ -732,7 +732,7 @@ If the value is a string select the string value }; } - private static Action? MergeSourceScheme(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergeSourceScheme(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { if (!dependencies.SourceScheme.Any() || dependencies.Files.Contains("resource\\sourcescheme.res")) { @@ -966,7 +966,7 @@ void RemoveBaseSchemeValues(string folderPath, IEnumerable baseFiles) }; } - private static Action? MergeLanguageTokens(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergeLanguageTokens(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { if (dependencies.LanguageTokens.Count == 0) { @@ -980,7 +980,7 @@ void RemoveBaseSchemeValues(string folderPath, IEnumerable baseFiles) List languages = ["english"]; - string settingsLanguage = ((App)Application.Current).Settings.Value.Language; + string settingsLanguage = settingsService.Settings.Language; if (settingsLanguage != "english") { @@ -1103,7 +1103,7 @@ void RemoveBaseSchemeValues(string folderPath, IEnumerable baseFiles) }; } - private static Action? MergeImages(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergeImages(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { IEnumerable images = dependencies.Images.Concat(dependencies.PreloadImages); @@ -1132,7 +1132,7 @@ void RemoveBaseSchemeValues(string folderPath, IEnumerable baseFiles) return null; } - private static Action? MergePreloadImages(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergePreloadImages(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { if (dependencies.PreloadImages.Count == 0) { @@ -1198,13 +1198,13 @@ void RemoveBaseSchemeValues(string folderPath, IEnumerable baseFiles) }; } - private static Action? MergeAudio(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergeAudio(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { dependencies.Files.UnionWith(dependencies.Audio); return null; } - private static Action? MergeInfoVDF(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? MergeInfoVDF(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { reader.Require([ (target, "info.vdf", FileType.VDF) @@ -1233,7 +1233,7 @@ void RemoveBaseSchemeValues(string folderPath, IEnumerable baseFiles) }; } - private static Action? CopyFiles(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies) + private static Action? CopyFiles(IHUDFileReaderService reader, HUD source, HUD target, Dependencies dependencies, ISettingsService settingsService) { return (writer) => { diff --git a/src/HUDMerger/Models/HUDLayout.cs b/src/HUDMerger.Core/Models/HUDLayout.cs similarity index 96% rename from src/HUDMerger/Models/HUDLayout.cs rename to src/HUDMerger.Core/Models/HUDLayout.cs index 36bbe5d..432c6a5 100644 --- a/src/HUDMerger/Models/HUDLayout.cs +++ b/src/HUDMerger.Core/Models/HUDLayout.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using HUDMerger.Extensions; -using HUDMerger.Services; +using HUDMerger.Core.Extensions; +using HUDMerger.Core.Services; using VDF; using VDF.Models; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; public class HUDLayout { diff --git a/src/HUDMerger/Models/HUDPanel.cs b/src/HUDMerger.Core/Models/HUDPanel.cs similarity index 90% rename from src/HUDMerger/Models/HUDPanel.cs rename to src/HUDMerger.Core/Models/HUDPanel.cs index e1a3170..5d329b4 100644 --- a/src/HUDMerger/Models/HUDPanel.cs +++ b/src/HUDMerger.Core/Models/HUDPanel.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; public record class HUDPanel { diff --git a/src/HUDMerger/Models/KeyValueLocation.cs b/src/HUDMerger.Core/Models/KeyValueLocation.cs similarity index 91% rename from src/HUDMerger/Models/KeyValueLocation.cs rename to src/HUDMerger.Core/Models/KeyValueLocation.cs index dde3501..b23c50c 100644 --- a/src/HUDMerger/Models/KeyValueLocation.cs +++ b/src/HUDMerger.Core/Models/KeyValueLocation.cs @@ -1,6 +1,6 @@ using System; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; /// /// Stores a file and key path to a Key/Value diff --git a/src/HUDMerger/Models/Scheme/ClientScheme.cs b/src/HUDMerger.Core/Models/Scheme/ClientScheme.cs similarity index 84% rename from src/HUDMerger/Models/Scheme/ClientScheme.cs rename to src/HUDMerger.Core/Models/Scheme/ClientScheme.cs index 775dbc7..e74c243 100644 --- a/src/HUDMerger/Models/Scheme/ClientScheme.cs +++ b/src/HUDMerger.Core/Models/Scheme/ClientScheme.cs @@ -1,8 +1,8 @@ using System; -using HUDMerger.Services; +using HUDMerger.Core.Services; using VDF.Models; -namespace HUDMerger.Models.Scheme; +namespace HUDMerger.Core.Models.Scheme; public class ClientScheme : SchemeBase { diff --git a/src/HUDMerger/Models/Scheme/IScheme.cs b/src/HUDMerger.Core/Models/Scheme/IScheme.cs similarity index 93% rename from src/HUDMerger/Models/Scheme/IScheme.cs rename to src/HUDMerger.Core/Models/Scheme/IScheme.cs index a36fe79..031f077 100644 --- a/src/HUDMerger/Models/Scheme/IScheme.cs +++ b/src/HUDMerger.Core/Models/Scheme/IScheme.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using VDF.Models; -namespace HUDMerger.Models.Scheme; +namespace HUDMerger.Core.Models.Scheme; public interface IScheme { diff --git a/src/HUDMerger/Models/Scheme/SchemeBase.cs b/src/HUDMerger.Core/Models/Scheme/SchemeBase.cs similarity index 98% rename from src/HUDMerger/Models/Scheme/SchemeBase.cs rename to src/HUDMerger.Core/Models/Scheme/SchemeBase.cs index c0b13d3..84c72d6 100644 --- a/src/HUDMerger/Models/Scheme/SchemeBase.cs +++ b/src/HUDMerger.Core/Models/Scheme/SchemeBase.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using HUDMerger.Extensions; -using HUDMerger.Services; +using HUDMerger.Core.Extensions; +using HUDMerger.Core.Services; using VDF; using VDF.Models; -namespace HUDMerger.Models.Scheme; +namespace HUDMerger.Core.Models.Scheme; public abstract class SchemeBase : IScheme { @@ -326,7 +326,7 @@ static KeyValues ConvertSchemeToKeyValues(Dictionary dictionary) if (CustomFontFiles.Count != 0) { - List customFontFilesList = [..CustomFontFiles]; + List customFontFilesList = [.. CustomFontFiles]; customFontFilesList.Sort((a, b) => { if (int.TryParse(a.Key, out int first) && int.TryParse(b.Key, out int second)) diff --git a/src/HUDMerger/Models/Scheme/SourceScheme.cs b/src/HUDMerger.Core/Models/Scheme/SourceScheme.cs similarity index 84% rename from src/HUDMerger/Models/Scheme/SourceScheme.cs rename to src/HUDMerger.Core/Models/Scheme/SourceScheme.cs index 9cd2ebb..1253804 100644 --- a/src/HUDMerger/Models/Scheme/SourceScheme.cs +++ b/src/HUDMerger.Core/Models/Scheme/SourceScheme.cs @@ -1,8 +1,8 @@ using System; -using HUDMerger.Services; +using HUDMerger.Core.Services; using VDF.Models; -namespace HUDMerger.Models.Scheme; +namespace HUDMerger.Core.Models.Scheme; public class SourceScheme : SchemeBase { diff --git a/src/HUDMerger/Models/SchemeDependencies.cs b/src/HUDMerger.Core/Models/SchemeDependencies.cs similarity index 94% rename from src/HUDMerger/Models/SchemeDependencies.cs rename to src/HUDMerger.Core/Models/SchemeDependencies.cs index df0eaca..07225cb 100644 --- a/src/HUDMerger/Models/SchemeDependencies.cs +++ b/src/HUDMerger.Core/Models/SchemeDependencies.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; public class SchemeDependencies { diff --git a/src/HUDMerger/Models/Settings.cs b/src/HUDMerger.Core/Models/Settings.cs similarity index 81% rename from src/HUDMerger/Models/Settings.cs rename to src/HUDMerger.Core/Models/Settings.cs index 9081698..fc37317 100644 --- a/src/HUDMerger/Models/Settings.cs +++ b/src/HUDMerger.Core/Models/Settings.cs @@ -1,6 +1,6 @@ using System; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; public class Settings { diff --git a/src/HUDMerger/Models/VPK.cs b/src/HUDMerger.Core/Models/VPK.cs similarity index 98% rename from src/HUDMerger/Models/VPK.cs rename to src/HUDMerger.Core/Models/VPK.cs index 28b4b8d..3c182e3 100644 --- a/src/HUDMerger/Models/VPK.cs +++ b/src/HUDMerger.Core/Models/VPK.cs @@ -3,9 +3,9 @@ using System.IO; using System.Text; using System.Text.RegularExpressions; -using HUDMerger.Extensions; +using HUDMerger.Core.Extensions; -namespace HUDMerger.Models; +namespace HUDMerger.Core.Models; /// /// https://developer.valvesoftware.com/wiki/VPK_(file_format) diff --git a/src/HUDMerger/Resources/Dependencies.json b/src/HUDMerger.Core/Resources/Dependencies.json similarity index 100% rename from src/HUDMerger/Resources/Dependencies.json rename to src/HUDMerger.Core/Resources/Dependencies.json diff --git a/src/HUDMerger/Resources/Panels.json b/src/HUDMerger.Core/Resources/Panels.json similarity index 100% rename from src/HUDMerger/Resources/Panels.json rename to src/HUDMerger.Core/Resources/Panels.json diff --git a/src/HUDMerger/Services/HUDFileReaderService.cs b/src/HUDMerger.Core/Services/HUDFileReaderService.cs similarity index 84% rename from src/HUDMerger/Services/HUDFileReaderService.cs rename to src/HUDMerger.Core/Services/HUDFileReaderService.cs index 4af7ee8..dcf79f8 100644 --- a/src/HUDMerger/Services/HUDFileReaderService.cs +++ b/src/HUDMerger.Core/Services/HUDFileReaderService.cs @@ -6,14 +6,14 @@ using System.Windows; using HUDAnimations; using HUDAnimations.Models; -using HUDMerger.Exceptions; -using HUDMerger.Extensions; -using HUDMerger.Models; +using HUDMerger.Core.Exceptions; +using HUDMerger.Core.Extensions; +using HUDMerger.Core.Models; using VDF; using VDF.Exceptions; using VDF.Models; -namespace HUDMerger.Services; +namespace HUDMerger.Core.Services; public enum FileType : byte { @@ -23,11 +23,20 @@ public enum FileType : byte public partial class HUDFileReaderService : IHUDFileReaderService { - private readonly Lazy TF2MiscDirVPK = new(() => new(Path.Join(((App)Application.Current).Settings.Value.TeamFortress2Folder, "tf\\tf2_misc_dir.vpk"))); - private readonly Lazy PlatformMiscDirVPK = new(() => new(Path.Join(((App)Application.Current).Settings.Value.TeamFortress2Folder, "platform\\platform_misc_dir.vpk"))); + private readonly ISettingsService SettingsService; + + private readonly Lazy TF2MiscDirVPK; + private readonly Lazy PlatformMiscDirVPK; private readonly Dictionary Files = []; + public HUDFileReaderService(ISettingsService settingsService) + { + SettingsService = settingsService; + TF2MiscDirVPK = new Lazy(() => new VPK(Path.Join(SettingsService.Settings.TeamFortress2Folder, "tf\\tf2_misc_dir.vpk"))); + PlatformMiscDirVPK = new Lazy(() => new VPK(Path.Join(SettingsService.Settings.TeamFortress2Folder, "platform\\platform_misc_dir.vpk"))); + } + public void Require(IEnumerable<(HUD hud, string relativePath, FileType type)> filePaths) { HashSet seen = []; @@ -65,13 +74,13 @@ void Add(HUD hud, string relativePath, FileType type) return Encoding.UTF8.GetString(PlatformMiscDirVPK.Value.Read(relativePath)); } - string tfPath = Path.Join(((App)Application.Current).Settings.Value.TeamFortress2Folder, "tf", relativePath); + string tfPath = Path.Join(SettingsService.Settings.TeamFortress2Folder, "tf", relativePath); if (File.Exists(tfPath)) { return File.ReadAllText(tfPath); } - string hl2Path = Path.Join(((App)Application.Current).Settings.Value.TeamFortress2Folder, "hl2", relativePath); + string hl2Path = Path.Join(SettingsService.Settings.TeamFortress2Folder, "hl2", relativePath); if (File.Exists(hl2Path)) { return File.ReadAllText(hl2Path); diff --git a/src/HUDMerger/Services/HUDFileWriterService.cs b/src/HUDMerger.Core/Services/HUDFileWriterService.cs similarity index 95% rename from src/HUDMerger/Services/HUDFileWriterService.cs rename to src/HUDMerger.Core/Services/HUDFileWriterService.cs index 545ceff..f142964 100644 --- a/src/HUDMerger/Services/HUDFileWriterService.cs +++ b/src/HUDMerger.Core/Services/HUDFileWriterService.cs @@ -3,11 +3,11 @@ using System.Text; using HUDAnimations; using HUDAnimations.Models; -using HUDMerger.Models; +using HUDMerger.Core.Models; using VDF; using VDF.Models; -namespace HUDMerger.Services; +namespace HUDMerger.Core.Services; public class HUDFileWriterService(string folderPath) : IHUDFileWriterService { diff --git a/src/HUDMerger.Core/Services/IAboutWindowService.cs b/src/HUDMerger.Core/Services/IAboutWindowService.cs new file mode 100644 index 0000000..04c41cb --- /dev/null +++ b/src/HUDMerger.Core/Services/IAboutWindowService.cs @@ -0,0 +1,9 @@ +using System; +using HUDMerger.Core.ViewModels; + +namespace HUDMerger.Core.Services; + +public interface IAboutWindowService +{ + public void Show(AboutWindowViewModel aboutWindowViewModel); +} diff --git a/src/HUDMerger.Core/Services/IFolderPickerService.cs b/src/HUDMerger.Core/Services/IFolderPickerService.cs new file mode 100644 index 0000000..4dd399d --- /dev/null +++ b/src/HUDMerger.Core/Services/IFolderPickerService.cs @@ -0,0 +1,9 @@ +using System; +using System.Threading.Tasks; + +namespace HUDMerger.Core.Services; + +public interface IFolderPickerService +{ + public Task PickFolderAsync(); +} diff --git a/src/HUDMerger/Services/IHUDFileReaderService.cs b/src/HUDMerger.Core/Services/IHUDFileReaderService.cs similarity index 88% rename from src/HUDMerger/Services/IHUDFileReaderService.cs rename to src/HUDMerger.Core/Services/IHUDFileReaderService.cs index f8a47c5..72b2fde 100644 --- a/src/HUDMerger/Services/IHUDFileReaderService.cs +++ b/src/HUDMerger.Core/Services/IHUDFileReaderService.cs @@ -1,10 +1,10 @@ using System; using System.Collections.Generic; using HUDAnimations.Models; -using HUDMerger.Models; +using HUDMerger.Core.Models; using VDF.Models; -namespace HUDMerger.Services; +namespace HUDMerger.Core.Services; public interface IHUDFileReaderService { diff --git a/src/HUDMerger/Services/IHUDFileWriterService.cs b/src/HUDMerger.Core/Services/IHUDFileWriterService.cs similarity index 85% rename from src/HUDMerger/Services/IHUDFileWriterService.cs rename to src/HUDMerger.Core/Services/IHUDFileWriterService.cs index a405daf..c6a2bab 100644 --- a/src/HUDMerger/Services/IHUDFileWriterService.cs +++ b/src/HUDMerger.Core/Services/IHUDFileWriterService.cs @@ -1,10 +1,10 @@ using System; using System.Text; using HUDAnimations.Models; -using HUDMerger.Models; +using HUDMerger.Core.Models; using VDF.Models; -namespace HUDMerger.Services; +namespace HUDMerger.Core.Services; public interface IHUDFileWriterService { diff --git a/src/HUDMerger.Core/Services/IMessageBoxService.cs b/src/HUDMerger.Core/Services/IMessageBoxService.cs new file mode 100644 index 0000000..6e8bf60 --- /dev/null +++ b/src/HUDMerger.Core/Services/IMessageBoxService.cs @@ -0,0 +1,9 @@ +using System; + +namespace HUDMerger.Core.Services; + +public interface IMessageBoxService +{ + public void Show(string messageBoxText); + public void ShowException(Exception exception, string caption); +} diff --git a/src/HUDMerger.Core/Services/IQuitService.cs b/src/HUDMerger.Core/Services/IQuitService.cs new file mode 100644 index 0000000..1a6e68e --- /dev/null +++ b/src/HUDMerger.Core/Services/IQuitService.cs @@ -0,0 +1,8 @@ +using System; + +namespace HUDMerger.Core.Services; + +public interface IQuitService +{ + public void Quit(); +} diff --git a/src/HUDMerger.Core/Services/ISettingsService.cs b/src/HUDMerger.Core/Services/ISettingsService.cs new file mode 100644 index 0000000..704630c --- /dev/null +++ b/src/HUDMerger.Core/Services/ISettingsService.cs @@ -0,0 +1,10 @@ +using System; +using HUDMerger.Core.Models; + +namespace HUDMerger.Core.Services; + +public interface ISettingsService +{ + public Settings Settings { get; } + public void Save(); +} diff --git a/src/HUDMerger.Core/Services/ISettingsWindowService.cs b/src/HUDMerger.Core/Services/ISettingsWindowService.cs new file mode 100644 index 0000000..8e898b5 --- /dev/null +++ b/src/HUDMerger.Core/Services/ISettingsWindowService.cs @@ -0,0 +1,9 @@ +using System; +using HUDMerger.Core.ViewModels; + +namespace HUDMerger.Core.Services; + +public interface ISettingsWindowService +{ + public void Show(SettingsWindowViewModel settingsWindowViewModel); +} diff --git a/src/HUDMerger/ViewModels/AboutWindowViewModel.cs b/src/HUDMerger.Core/ViewModels/AboutWindowViewModel.cs similarity index 94% rename from src/HUDMerger/ViewModels/AboutWindowViewModel.cs rename to src/HUDMerger.Core/ViewModels/AboutWindowViewModel.cs index a0cb492..b1f8c84 100644 --- a/src/HUDMerger/ViewModels/AboutWindowViewModel.cs +++ b/src/HUDMerger.Core/ViewModels/AboutWindowViewModel.cs @@ -3,7 +3,7 @@ using System.Windows.Input; using Microsoft.Toolkit.Mvvm.Input; -namespace HUDMerger.ViewModels; +namespace HUDMerger.Core.ViewModels; public class AboutWindowViewModel : ViewModelBase { diff --git a/src/HUDMerger/ViewModels/HUDInfoViewModel.cs b/src/HUDMerger.Core/ViewModels/HUDInfoViewModel.cs similarity index 87% rename from src/HUDMerger/ViewModels/HUDInfoViewModel.cs rename to src/HUDMerger.Core/ViewModels/HUDInfoViewModel.cs index 447ad58..fbc06a3 100644 --- a/src/HUDMerger/ViewModels/HUDInfoViewModel.cs +++ b/src/HUDMerger.Core/ViewModels/HUDInfoViewModel.cs @@ -1,7 +1,7 @@ using System; -using HUDMerger.Models; +using HUDMerger.Core.Models; -namespace HUDMerger.ViewModels; +namespace HUDMerger.Core.ViewModels; public class HUDInfoViewModel(string locationType, HUD? hud) : ViewModelBase { diff --git a/src/HUDMerger/ViewModels/HUDPanelViewModel.cs b/src/HUDMerger.Core/ViewModels/HUDPanelViewModel.cs similarity index 89% rename from src/HUDMerger/ViewModels/HUDPanelViewModel.cs rename to src/HUDMerger.Core/ViewModels/HUDPanelViewModel.cs index e68b187..64f0fd7 100644 --- a/src/HUDMerger/ViewModels/HUDPanelViewModel.cs +++ b/src/HUDMerger.Core/ViewModels/HUDPanelViewModel.cs @@ -1,9 +1,9 @@ using System; using System.Windows.Input; -using HUDMerger.Models; +using HUDMerger.Core.Models; using Microsoft.Toolkit.Mvvm.Input; -namespace HUDMerger.ViewModels; +namespace HUDMerger.Core.ViewModels; public class HUDPanelViewModel : ViewModelBase { diff --git a/src/HUDMerger/ViewModels/MainWindowViewModel.cs b/src/HUDMerger.Core/ViewModels/MainWindowViewModel.cs similarity index 63% rename from src/HUDMerger/ViewModels/MainWindowViewModel.cs rename to src/HUDMerger.Core/ViewModels/MainWindowViewModel.cs index b5f3bc2..5c1f14e 100644 --- a/src/HUDMerger/ViewModels/MainWindowViewModel.cs +++ b/src/HUDMerger.Core/ViewModels/MainWindowViewModel.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; @@ -8,19 +8,19 @@ using System.Windows; using System.Windows.Input; using Discord; -using HUDMerger.Commands; -using HUDMerger.Models; +using HUDMerger.Core.Commands; +using HUDMerger.Core.Models; +using HUDMerger.Core.Services; using Microsoft.Toolkit.Mvvm.Input; -using Microsoft.Win32; -namespace HUDMerger.ViewModels; +namespace HUDMerger.Core.ViewModels; public class MainWindowViewModel : ViewModelBase { - private static readonly OpenFolderDialog OpenFolderDialog = new() - { - InitialDirectory = Path.Join(((App)Application.Current).Settings.Value.TeamFortress2Folder, "tf\\custom\\") - }; + private readonly ISettingsService SettingsService; + private readonly IFolderPickerService FolderPickerService; + private readonly ISettingsWindowService SettingsWindowService; + private readonly IAboutWindowService AboutWindowService; private static readonly Channel<(string? sourceName, string? targetName)> DiscordChannel = Channel.CreateBounded<(string? sourceName, string? targetName)>(new BoundedChannelOptions(1) { FullMode = BoundedChannelFullMode.DropOldest }); @@ -86,12 +86,17 @@ public ViewModelBase TargetHUDPanelsListViewModel public MergeCommand MergeCommand { get; } - public MainWindowViewModel() + public MainWindowViewModel(ISettingsService settingsService, IFolderPickerService folderPickerService, ISettingsWindowService settingsWindowService, IAboutWindowService aboutWindowService, IQuitService quitService, IMessageBoxService messageBoxService) { - LoadSourceHUDCommand = new RelayCommand(LoadSourceHUD); - LoadTargetHUDCommand = new RelayCommand(LoadTargetHUD); + SettingsService = settingsService; + FolderPickerService = folderPickerService; + SettingsWindowService = settingsWindowService; + AboutWindowService = aboutWindowService; + + LoadSourceHUDCommand = new AsyncRelayCommand(LoadSourceHUD); + LoadTargetHUDCommand = new AsyncRelayCommand(LoadTargetHUD); ShowSettingsWindowCommand = new RelayCommand(ShowSettingsWindow); - QuitCommand = new RelayCommand(Application.Current.Shutdown); + QuitCommand = new RelayCommand(quitService.Quit); ShowAboutWindowCommand = new RelayCommand(ShowAboutWindow); @@ -101,7 +106,7 @@ public MainWindowViewModel() _sourceHUDPanelsListViewModel = new SelectHUDViewModel(LoadSourceHUDCommand); _targetHUDPanelsListViewModel = new SelectHUDViewModel(LoadTargetHUDCommand); - MergeCommand = new MergeCommand(this); + MergeCommand = new MergeCommand(this, SettingsService, messageBoxService); ChannelReader<(string? sourceName, string? targetName)> reader = DiscordChannel.Reader; Task.Run(async () => await DiscordRichPresence(reader)); @@ -109,81 +114,63 @@ public MainWindowViewModel() private void ShowSettingsWindow() { - using SettingsWindowViewModel settingsWindowViewModel = new(); - - SettingsWindow settingsWindow = new() - { - DataContext = settingsWindowViewModel, - Owner = Application.Current.MainWindow - }; - - void OnClose(object? sender, EventArgs args) - { - settingsWindowViewModel.Close -= OnClose; - settingsWindow.Close(); - } - - settingsWindowViewModel.Close += OnClose; - - settingsWindow.Show(); + SettingsWindowService.Show(new SettingsWindowViewModel(SettingsService)); } private void ShowAboutWindow() { - using AboutWindowViewModel aboutWindowViewModel = new(); - - AboutWindow aboutWindow = new() - { - DataContext = aboutWindowViewModel, - Owner = Application.Current.MainWindow - }; - - aboutWindow.Show(); + AboutWindowService.Show(new AboutWindowViewModel()); } - private void LoadSourceHUD() + private async Task LoadSourceHUD() { - if (OpenFolderDialog.ShowDialog(Application.Current.MainWindow) == true) + string? folderName = await FolderPickerService.PickFolderAsync(); + if (folderName == null) { - SourceHUD = new HUD(OpenFolderDialog.FolderName); - SourceHUDInfoViewModel.HUD = SourceHUD; + return; + } - HUDPanelViewModels.Clear(); + SourceHUD = new HUD(folderName); + SourceHUDInfoViewModel.HUD = SourceHUD; - foreach (HUDPanel hudPanel in SourceHUD.Panels) - { - HUDPanelViewModel hudPanelViewModel = new(hudPanel); - hudPanelViewModel.PropertyChanged += HudPanelViewModel_PropertyChanged; - HUDPanelViewModels.Add(hudPanelViewModel); - } + HUDPanelViewModels.Clear(); - SourceHUDPanelsListViewModel?.Dispose(); - SourceHUDPanelsListViewModel = new SourceHUDPanelsListViewModel(HUDPanelViewModels); + foreach (HUDPanel hudPanel in SourceHUD.Panels) + { + HUDPanelViewModel hudPanelViewModel = new(hudPanel); + hudPanelViewModel.PropertyChanged += HudPanelViewModel_PropertyChanged; + HUDPanelViewModels.Add(hudPanelViewModel); + } - if (TargetHUDPanelsListViewModel is TargetHUDPanelsListViewModel targetHUDPanelsListViewModel) - { - targetHUDPanelsListViewModel.HUDPanelsCollectionView.Refresh(); - } + SourceHUDPanelsListViewModel?.Dispose(); + SourceHUDPanelsListViewModel = new SourceHUDPanelsListViewModel(HUDPanelViewModels); + + if (TargetHUDPanelsListViewModel is TargetHUDPanelsListViewModel targetHUDPanelsListViewModel) + { + targetHUDPanelsListViewModel.Refresh(); } } - private void LoadTargetHUD() + private async Task LoadTargetHUD() { - if (OpenFolderDialog.ShowDialog(Application.Current.MainWindow) == true) + string? folderName = await FolderPickerService.PickFolderAsync(); + if (folderName == null) { - TargetHUD = new HUD(OpenFolderDialog.FolderName); - TargetHUDInfoViewModel.HUD = TargetHUD; - - TargetHUDPanelsListViewModel?.Dispose(); - TargetHUDPanelsListViewModel = new TargetHUDPanelsListViewModel(HUDPanelViewModels); + return; } + + TargetHUD = new HUD(folderName); + TargetHUDInfoViewModel.HUD = TargetHUD; + + TargetHUDPanelsListViewModel?.Dispose(); + TargetHUDPanelsListViewModel = new TargetHUDPanelsListViewModel(HUDPanelViewModels); } private void HudPanelViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(HUDPanelViewModel.Selected) && TargetHUDPanelsListViewModel is TargetHUDPanelsListViewModel targetHUDPanelsListViewModel) { - targetHUDPanelsListViewModel.HUDPanelsCollectionView.Refresh(); + targetHUDPanelsListViewModel.Refresh(); } } diff --git a/src/HUDMerger/ViewModels/SelectHUDViewModel.cs b/src/HUDMerger.Core/ViewModels/SelectHUDViewModel.cs similarity index 83% rename from src/HUDMerger/ViewModels/SelectHUDViewModel.cs rename to src/HUDMerger.Core/ViewModels/SelectHUDViewModel.cs index 5422533..017526a 100644 --- a/src/HUDMerger/ViewModels/SelectHUDViewModel.cs +++ b/src/HUDMerger.Core/ViewModels/SelectHUDViewModel.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Input; -namespace HUDMerger.ViewModels; +namespace HUDMerger.Core.ViewModels; public class SelectHUDViewModel(ICommand selectHUDCommand) : ViewModelBase { diff --git a/src/HUDMerger/ViewModels/SettingsWindowViewModel.cs b/src/HUDMerger.Core/ViewModels/SettingsWindowViewModel.cs similarity index 59% rename from src/HUDMerger/ViewModels/SettingsWindowViewModel.cs rename to src/HUDMerger.Core/ViewModels/SettingsWindowViewModel.cs index 541185f..f5b953c 100644 --- a/src/HUDMerger/ViewModels/SettingsWindowViewModel.cs +++ b/src/HUDMerger.Core/ViewModels/SettingsWindowViewModel.cs @@ -1,13 +1,16 @@ using System; using System.Windows; using System.Windows.Input; -using HUDMerger.Models; +using HUDMerger.Core.Models; +using HUDMerger.Core.Services; using Microsoft.Toolkit.Mvvm.Input; -namespace HUDMerger.ViewModels; +namespace HUDMerger.Core.ViewModels; public class SettingsWindowViewModel : ViewModelBase { + private readonly ISettingsService SettingsService; + private string _teamFortress2Folder; public string TeamFortress2Folder { @@ -35,12 +38,12 @@ public string Language public event EventHandler? Close; - public SettingsWindowViewModel() + public SettingsWindowViewModel(ISettingsService settingsService) { - Settings settings = ((App)Application.Current).Settings.Value; + SettingsService = settingsService; - _teamFortress2Folder = settings.TeamFortress2Folder; - _language = settings.Language; + _teamFortress2Folder = SettingsService.Settings.TeamFortress2Folder; + _language = SettingsService.Settings.Language; CancelCommand = new RelayCommand(Cancel); ApplyCommand = new RelayCommand(Apply); @@ -53,12 +56,9 @@ private void Cancel() private void Apply() { - ((App)Application.Current).Settings.Value.TeamFortress2Folder = TeamFortress2Folder; - ((App)Application.Current).Settings.Value.Language = Language; - - Properties.Settings.Default.TeamFortress2Folder = TeamFortress2Folder; - Properties.Settings.Default.Language = Language; - Properties.Settings.Default.Save(); + SettingsService.Settings.TeamFortress2Folder = TeamFortress2Folder; + SettingsService.Settings.Language = Language; + SettingsService.Save(); Close?.Invoke(this, new EventArgs()); } diff --git a/src/HUDMerger.Core/ViewModels/SourceHUDPanelsListViewModel.cs b/src/HUDMerger.Core/ViewModels/SourceHUDPanelsListViewModel.cs new file mode 100644 index 0000000..db556b1 --- /dev/null +++ b/src/HUDMerger.Core/ViewModels/SourceHUDPanelsListViewModel.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace HUDMerger.Core.ViewModels; + +public class SourceHUDPanelsListViewModel : ViewModelBase +{ + private readonly IEnumerable HUDPanelViewModels; + + private ObservableCollection _hudPanelsCollectionView; + public ObservableCollection HUDPanelsCollectionView + { + get => _hudPanelsCollectionView; + private set + { + _hudPanelsCollectionView = value; + OnPropertyChanged(); + } + } + + private string _searchText = ""; + public string SearchText + { + get => _searchText; + set + { + _searchText = value; + OnPropertyChanged(); + Refresh(); + } + } + + public SourceHUDPanelsListViewModel(IEnumerable hudPanelViewModels) + { + HUDPanelViewModels = hudPanelViewModels; + _hudPanelsCollectionView = new ObservableCollection( + HUDPanelViewModels.Where((hudPanelViewModel) => + { + return hudPanelViewModel.HUDPanel.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase) + || hudPanelViewModel.HUDPanel.Main.Contains(SearchText, StringComparison.OrdinalIgnoreCase); + }) + ); + } + + public void Refresh() + { + HUDPanelsCollectionView = new ObservableCollection( + HUDPanelViewModels.Where((hudPanelViewModel) => + { + return hudPanelViewModel.HUDPanel.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase) + || hudPanelViewModel.HUDPanel.Main.Contains(SearchText, StringComparison.OrdinalIgnoreCase); + }) + ); + } +} diff --git a/src/HUDMerger.Core/ViewModels/TargetHUDPanelsListViewModel.cs b/src/HUDMerger.Core/ViewModels/TargetHUDPanelsListViewModel.cs new file mode 100644 index 0000000..ff5b8d8 --- /dev/null +++ b/src/HUDMerger.Core/ViewModels/TargetHUDPanelsListViewModel.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace HUDMerger.Core.ViewModels; + +public class TargetHUDPanelsListViewModel : ViewModelBase +{ + private readonly IEnumerable HUDPanelViewModels; + + private ObservableCollection _hudPanelsCollectionView; + public ObservableCollection HUDPanelsCollectionView + { + get => _hudPanelsCollectionView; + private set + { + _hudPanelsCollectionView = value; + OnPropertyChanged(); + } + } + + public TargetHUDPanelsListViewModel(IEnumerable hudPanelViewModels) + { + HUDPanelViewModels = hudPanelViewModels; + _hudPanelsCollectionView = new ObservableCollection( + HUDPanelViewModels.Where((hudPanelViewModel) => + { + return hudPanelViewModel.Selected; + }) + ); + } + + public void Refresh() + { + HUDPanelsCollectionView = new ObservableCollection( + HUDPanelViewModels.Where((hudPanelViewModel) => + { + return hudPanelViewModel.Selected; + }) + ); + } +} diff --git a/src/HUDMerger/ViewModels/ViewModelBase.cs b/src/HUDMerger.Core/ViewModels/ViewModelBase.cs similarity index 94% rename from src/HUDMerger/ViewModels/ViewModelBase.cs rename to src/HUDMerger.Core/ViewModels/ViewModelBase.cs index ab990c2..2d90ac2 100644 --- a/src/HUDMerger/ViewModels/ViewModelBase.cs +++ b/src/HUDMerger.Core/ViewModels/ViewModelBase.cs @@ -2,7 +2,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; -namespace HUDMerger.ViewModels; +namespace HUDMerger.Core.ViewModels; public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable { diff --git a/src/HUDMerger.sln b/src/HUDMerger.sln index 06b276e..2cfd572 100644 --- a/src/HUDMerger.sln +++ b/src/HUDMerger.sln @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HUDAnimations", "HUDAnimati EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HUDAnimationsTests", "HUDAnimationsTests\HUDAnimationsTests.csproj", "{4E30AF72-1594-41C3-9732-4CD3F4494112}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HUDMerger.Core", "HUDMerger.Core\HUDMerger.Core.csproj", "{BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -83,6 +85,18 @@ Global {4E30AF72-1594-41C3-9732-4CD3F4494112}.Release|x64.Build.0 = Release|Any CPU {4E30AF72-1594-41C3-9732-4CD3F4494112}.Release|x86.ActiveCfg = Release|Any CPU {4E30AF72-1594-41C3-9732-4CD3F4494112}.Release|x86.Build.0 = Release|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Debug|x64.ActiveCfg = Debug|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Debug|x64.Build.0 = Debug|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Debug|x86.ActiveCfg = Debug|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Debug|x86.Build.0 = Debug|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Release|Any CPU.Build.0 = Release|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Release|x64.ActiveCfg = Release|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Release|x64.Build.0 = Release|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Release|x86.ActiveCfg = Release|Any CPU + {BCD71204-8FEC-4B6C-A264-FBB6AB5C6CDB}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/HUDMerger/App.xaml.cs b/src/HUDMerger/App.xaml.cs index 792ffd8..d40c1c5 100644 --- a/src/HUDMerger/App.xaml.cs +++ b/src/HUDMerger/App.xaml.cs @@ -3,9 +3,10 @@ using System.Linq; using System.Text.RegularExpressions; using System.Windows; -using HUDMerger.Extensions; -using HUDMerger.Models; -using HUDMerger.ViewModels; +using HUDMerger.Core.Extensions; +using HUDMerger.Core.Models; +using HUDMerger.Core.ViewModels; +using HUDMerger.Services; using Microsoft.Win32; using VDF; using VDF.Models; @@ -17,94 +18,6 @@ namespace HUDMerger; /// public partial class App : Application { - [GeneratedRegex(@"[/\\]+")] - public static partial Regex PathSeparatorRegex(); - - public Lazy Settings = new(() => - { - string? teamFortress2Folder = null; - if (!string.IsNullOrEmpty(HUDMerger.Properties.Settings.Default.TeamFortress2Folder)) - { - teamFortress2Folder = HUDMerger.Properties.Settings.Default.TeamFortress2Folder; - } - - string? language = null; - if (!string.IsNullOrEmpty(HUDMerger.Properties.Settings.Default.Language)) - { - language = HUDMerger.Properties.Settings.Default.Language; - } - - if (teamFortress2Folder == null || language == null) - { - try - { - // "C:\Program Files (x86)\Steam" - string? installPath = ( - Registry.GetValue($"HKEY_LOCAL_MACHINE\\Software\\{(Environment.Is64BitProcess ? "Wow6432Node\\" : "")}Valve\\Steam", "InstallPath", "") is string str - ? str - : null - ) ?? throw new Exception(); - - if (teamFortress2Folder == null) - { - try - { - KeyValues libraryFolder = VDFSerializer - .Deserialize(File.ReadAllText(Path.Join(installPath, "steamapps\\libraryfolders.vdf"))) - .Header("libraryfolders") - .First((keyValue) => - keyValue.Value is KeyValues indexValues && indexValues.Any((kv) => kv.Key.Equals("apps") && kv.Value is KeyValues appsKeyValues && appsKeyValues.Any((kv) => kv.Key == "440")) - ) - .Value; - - string libraryFolderPath = libraryFolder.First((kv) => kv.Key.Equals("path", StringComparison.OrdinalIgnoreCase) && kv.Value is string str).Value; - - string libraryFolderTeamFortress2Path = $"{libraryFolderPath.Replace("\\\\", "\\")}\\steamapps\\common\\Team Fortress 2"; - if (Directory.Exists(libraryFolderTeamFortress2Path)) - { - teamFortress2Folder = libraryFolderTeamFortress2Path; - } - } - catch (Exception) - { - } - } - - if (language == null) - { - try - { - string appManifestPath = Path.Join(installPath, "steamapps\\appmanifest_440.acf"); - - KeyValues userConfig = VDFSerializer - .Deserialize(File.ReadAllText(Path.Join(installPath, "steamapps\\appmanifest_440.acf"))) - .Header("AppState") - .First((kv) => kv.Key.Equals("UserConfig", StringComparison.OrdinalIgnoreCase) && kv.Value is KeyValues) - .Value; - - string userConfigLanguage = userConfig - .First((kv) => kv.Key.Equals("language", StringComparison.OrdinalIgnoreCase) && kv.Value is string) - .Value; - - language = userConfigLanguage; - } - catch (Exception) - { - } - } - } - catch (Exception) - { - } - } - - return new Settings - { - TeamFortress2Folder = teamFortress2Folder ?? "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Team Fortress 2", - Language = language ?? "english" - }; - }); - protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); @@ -112,9 +25,18 @@ protected override void OnStartup(StartupEventArgs e) HUDMerger.Properties.Settings.Default.Upgrade(); HUDMerger.Properties.Settings.Default.Save(); + SettingsService settingsService = new(); + MainWindow = new MainWindow { - DataContext = new MainWindowViewModel() + DataContext = new MainWindowViewModel( + settingsService, + new FolderPickerService(settingsService), + new SettingsWindowService(), + new AboutWindowService(), + new QuitService(), + new MessageBoxService() + ) }; MainWindow.Show(); diff --git a/src/HUDMerger/HUDMerger.csproj b/src/HUDMerger/HUDMerger.csproj index c7d655b..d13f724 100644 --- a/src/HUDMerger/HUDMerger.csproj +++ b/src/HUDMerger/HUDMerger.csproj @@ -13,9 +13,8 @@ + - - diff --git a/src/HUDMerger/Services/AboutWindowService.cs b/src/HUDMerger/Services/AboutWindowService.cs new file mode 100644 index 0000000..5d3ea39 --- /dev/null +++ b/src/HUDMerger/Services/AboutWindowService.cs @@ -0,0 +1,20 @@ +using System; +using System.Windows; +using HUDMerger.Core.Services; +using HUDMerger.Core.ViewModels; + +namespace HUDMerger.Services; + +public class AboutWindowService : IAboutWindowService +{ + public void Show(AboutWindowViewModel aboutWindowViewModel) + { + AboutWindow aboutWindow = new() + { + DataContext = aboutWindowViewModel, + Owner = Application.Current.MainWindow + }; + + aboutWindow.Show(); + } +} diff --git a/src/HUDMerger/Services/FolderPickerService.cs b/src/HUDMerger/Services/FolderPickerService.cs new file mode 100644 index 0000000..58dff63 --- /dev/null +++ b/src/HUDMerger/Services/FolderPickerService.cs @@ -0,0 +1,30 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using System.Windows; +using HUDMerger.Core.Services; +using Microsoft.Win32; + +namespace HUDMerger.Services; + +public class FolderPickerService : IFolderPickerService +{ + private readonly OpenFolderDialog OpenFolderDialog; + + public FolderPickerService(ISettingsService settingsService) + { + OpenFolderDialog = new OpenFolderDialog + { + InitialDirectory = Path.Join(settingsService.Settings.TeamFortress2Folder, "tf\\custom\\") + }; + } + + public Task PickFolderAsync() + { + return Task.FromResult( + OpenFolderDialog.ShowDialog(Application.Current.MainWindow) == true + ? OpenFolderDialog.FolderName + : null + ); + } +} diff --git a/src/HUDMerger/Services/MessageBoxService.cs b/src/HUDMerger/Services/MessageBoxService.cs new file mode 100644 index 0000000..9716a2b --- /dev/null +++ b/src/HUDMerger/Services/MessageBoxService.cs @@ -0,0 +1,18 @@ +using System; +using System.Windows; +using HUDMerger.Core.Services; + +namespace HUDMerger.Services; + +public class MessageBoxService : IMessageBoxService +{ + public void Show(string messageBoxText) + { + MessageBox.Show(messageBoxText); + } + + public void ShowException(Exception exception, string caption) + { + MessageBox.Show(exception.Message, caption, MessageBoxButton.OK, MessageBoxImage.Error); + } +} diff --git a/src/HUDMerger/Services/QuitService.cs b/src/HUDMerger/Services/QuitService.cs new file mode 100644 index 0000000..c3283a4 --- /dev/null +++ b/src/HUDMerger/Services/QuitService.cs @@ -0,0 +1,13 @@ +using System; +using System.Windows; +using HUDMerger.Core.Services; + +namespace HUDMerger.Services; + +public class QuitService : IQuitService +{ + public void Quit() + { + Application.Current.Shutdown(); + } +} diff --git a/src/HUDMerger/Services/SettingsService.cs b/src/HUDMerger/Services/SettingsService.cs new file mode 100644 index 0000000..a469abc --- /dev/null +++ b/src/HUDMerger/Services/SettingsService.cs @@ -0,0 +1,108 @@ +using System; +using System.IO; +using System.Linq; +using HUDMerger.Core.Extensions; +using HUDMerger.Core.Models; +using HUDMerger.Core.Services; +using Microsoft.Win32; +using VDF; +using VDF.Models; + +namespace HUDMerger.Services; + +public class SettingsService : ISettingsService +{ + public Settings Settings { get; } + + public SettingsService() + { + string? teamFortress2Folder = null; + if (!string.IsNullOrEmpty(HUDMerger.Properties.Settings.Default.TeamFortress2Folder)) + { + teamFortress2Folder = HUDMerger.Properties.Settings.Default.TeamFortress2Folder; + } + + string? language = null; + if (!string.IsNullOrEmpty(HUDMerger.Properties.Settings.Default.Language)) + { + language = HUDMerger.Properties.Settings.Default.Language; + } + + if (teamFortress2Folder == null || language == null) + { + try + { + // "C:\Program Files (x86)\Steam" + string? installPath = ( + Registry.GetValue($"HKEY_LOCAL_MACHINE\\Software\\{(Environment.Is64BitProcess ? "Wow6432Node\\" : "")}Valve\\Steam", "InstallPath", "") is string str + ? str + : null + ) ?? throw new Exception(); + + if (teamFortress2Folder == null) + { + try + { + KeyValues libraryFolder = VDFSerializer + .Deserialize(File.ReadAllText(Path.Join(installPath, "steamapps\\libraryfolders.vdf"))) + .Header("libraryfolders") + .First((keyValue) => + keyValue.Value is KeyValues indexValues && indexValues.Any((kv) => kv.Key.Equals("apps") && kv.Value is KeyValues appsKeyValues && appsKeyValues.Any((kv) => kv.Key == "440")) + ) + .Value; + + string libraryFolderPath = libraryFolder.First((kv) => kv.Key.Equals("path", StringComparison.OrdinalIgnoreCase) && kv.Value is string str).Value; + + string libraryFolderTeamFortress2Path = $"{libraryFolderPath.Replace("\\\\", "\\")}\\steamapps\\common\\Team Fortress 2"; + if (Directory.Exists(libraryFolderTeamFortress2Path)) + { + teamFortress2Folder = libraryFolderTeamFortress2Path; + } + } + catch (Exception) + { + } + } + + if (language == null) + { + try + { + string appManifestPath = Path.Join(installPath, "steamapps\\appmanifest_440.acf"); + + KeyValues userConfig = VDFSerializer + .Deserialize(File.ReadAllText(Path.Join(installPath, "steamapps\\appmanifest_440.acf"))) + .Header("AppState") + .First((kv) => kv.Key.Equals("UserConfig", StringComparison.OrdinalIgnoreCase) && kv.Value is KeyValues) + .Value; + + string userConfigLanguage = userConfig + .First((kv) => kv.Key.Equals("language", StringComparison.OrdinalIgnoreCase) && kv.Value is string) + .Value; + + language = userConfigLanguage; + } + catch (Exception) + { + } + } + } + catch (Exception) + { + } + } + + Settings = new Settings + { + TeamFortress2Folder = teamFortress2Folder ?? "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Team Fortress 2", + Language = language ?? "english" + }; + } + + public void Save() + { + Properties.Settings.Default.TeamFortress2Folder = Settings.TeamFortress2Folder; + Properties.Settings.Default.Language = Settings.Language; + Properties.Settings.Default.Save(); + } +} diff --git a/src/HUDMerger/Services/SettingsWindowService.cs b/src/HUDMerger/Services/SettingsWindowService.cs new file mode 100644 index 0000000..e10f537 --- /dev/null +++ b/src/HUDMerger/Services/SettingsWindowService.cs @@ -0,0 +1,27 @@ +using System; +using System.Windows; +using HUDMerger.Core.Services; +using HUDMerger.Core.ViewModels; + +namespace HUDMerger.Services; + +public class SettingsWindowService : ISettingsWindowService +{ + public void Show(SettingsWindowViewModel settingsWindowViewModel) + { + SettingsWindow settingsWindow = new() + { + DataContext = settingsWindowViewModel, + Owner = Application.Current.MainWindow + }; + + void OnClose(object? sender, EventArgs args) + { + settingsWindowViewModel.Close -= OnClose; + settingsWindow.Close(); + } + + settingsWindowViewModel.Close += OnClose; + settingsWindow.Show(); + } +} diff --git a/src/HUDMerger/ViewModels/SourceHUDPanelsListViewModel.cs b/src/HUDMerger/ViewModels/SourceHUDPanelsListViewModel.cs deleted file mode 100644 index 641bf00..0000000 --- a/src/HUDMerger/ViewModels/SourceHUDPanelsListViewModel.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Windows.Data; - -namespace HUDMerger.ViewModels; - -public class SourceHUDPanelsListViewModel : ViewModelBase -{ - public ICollectionView HUDPanelsCollectionView { get; } - - private string _searchText = ""; - public string SearchText - { - get => _searchText; - set - { - _searchText = value; - OnPropertyChanged(); - HUDPanelsCollectionView.Refresh(); - } - } - - public SourceHUDPanelsListViewModel(IEnumerable hudPanelViewModels) - { - HUDPanelsCollectionView = new CollectionViewSource { Source = hudPanelViewModels }.View; - HUDPanelsCollectionView.Filter = (object obj) => - { - if (obj is HUDPanelViewModel hudPanelViewModel) - { - return hudPanelViewModel.HUDPanel.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase) - || hudPanelViewModel.HUDPanel.Main.Contains(SearchText, StringComparison.OrdinalIgnoreCase); - } - return false; - }; - } -} diff --git a/src/HUDMerger/ViewModels/TargetHUDPanelsListViewModel.cs b/src/HUDMerger/ViewModels/TargetHUDPanelsListViewModel.cs deleted file mode 100644 index b0a2237..0000000 --- a/src/HUDMerger/ViewModels/TargetHUDPanelsListViewModel.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Windows.Data; - -namespace HUDMerger.ViewModels; - -public class TargetHUDPanelsListViewModel : ViewModelBase -{ - public ICollectionView HUDPanelsCollectionView { get; } - - public TargetHUDPanelsListViewModel(IEnumerable hudPanelViewModels) - { - HUDPanelsCollectionView = new CollectionViewSource { Source = hudPanelViewModels }.View; - HUDPanelsCollectionView.Filter = (object obj) => - { - return obj is HUDPanelViewModel hudPanelViewModel && hudPanelViewModel.Selected; - }; - } -} diff --git a/src/HUDMerger/Views/AboutWindowView.xaml b/src/HUDMerger/Views/AboutWindowView.xaml index 887ca01..73dd83c 100644 --- a/src/HUDMerger/Views/AboutWindowView.xaml +++ b/src/HUDMerger/Views/AboutWindowView.xaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:HUDMerger.Views" - xmlns:viewmodels="clr-namespace:HUDMerger.ViewModels" + xmlns:viewmodels="clr-namespace:HUDMerger.Core.ViewModels;assembly=HUDMerger.Core" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type={x:Type viewmodels:AboutWindowViewModel}}"> diff --git a/src/HUDMerger/Views/HUDInfoView.xaml b/src/HUDMerger/Views/HUDInfoView.xaml index 9c1dd0d..c1780cb 100644 --- a/src/HUDMerger/Views/HUDInfoView.xaml +++ b/src/HUDMerger/Views/HUDInfoView.xaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:HUDMerger.Views" - xmlns:viewmodels="clr-namespace:HUDMerger.ViewModels" + xmlns:viewmodels="clr-namespace:HUDMerger.Core.ViewModels;assembly=HUDMerger.Core" mc:Ignorable="d" d:DesignHeight="74" d:DesignWidth="377" d:DataContext="{d:DesignInstance Type={x:Type viewmodels:HUDInfoViewModel}}"> diff --git a/src/HUDMerger/Views/HUDPanelView.xaml b/src/HUDMerger/Views/HUDPanelView.xaml index cabab09..9513044 100644 --- a/src/HUDMerger/Views/HUDPanelView.xaml +++ b/src/HUDMerger/Views/HUDPanelView.xaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:HUDMerger.Views" - xmlns:viewmodels="clr-namespace:HUDMerger.ViewModels" + xmlns:viewmodels="clr-namespace:HUDMerger.Core.ViewModels;assembly=HUDMerger.Core" xmlns:converters="clr-namespace:HUDMerger.Converters" mc:Ignorable="d" d:DesignHeight="31" d:DesignWidth="355" d:DataContext="{d:DesignInstance Type={x:Type viewmodels:HUDPanelViewModel}}"> diff --git a/src/HUDMerger/Views/MainWindowView.xaml b/src/HUDMerger/Views/MainWindowView.xaml index fdcdb62..d9354ae 100644 --- a/src/HUDMerger/Views/MainWindowView.xaml +++ b/src/HUDMerger/Views/MainWindowView.xaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:HUDMerger.Views" - xmlns:viewmodels="clr-namespace:HUDMerger.ViewModels" + xmlns:viewmodels="clr-namespace:HUDMerger.Core.ViewModels;assembly=HUDMerger.Core" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type={x:Type viewmodels:MainWindowViewModel}}"> diff --git a/src/HUDMerger/Views/SettingsWindowView.xaml b/src/HUDMerger/Views/SettingsWindowView.xaml index acc2802..682300b 100644 --- a/src/HUDMerger/Views/SettingsWindowView.xaml +++ b/src/HUDMerger/Views/SettingsWindowView.xaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:HUDMerger.Views" - xmlns:viewmodels="clr-namespace:HUDMerger.ViewModels" + xmlns:viewmodels="clr-namespace:HUDMerger.Core.ViewModels;assembly=HUDMerger.Core" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type={x:Type viewmodels:SettingsWindowViewModel}}"> diff --git a/src/HUDMerger/Views/SourceHUDPanelsListView.xaml b/src/HUDMerger/Views/SourceHUDPanelsListView.xaml index 3f18304..4325e78 100644 --- a/src/HUDMerger/Views/SourceHUDPanelsListView.xaml +++ b/src/HUDMerger/Views/SourceHUDPanelsListView.xaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:HUDMerger.Views" - xmlns:viewmodels="clr-namespace:HUDMerger.ViewModels" + xmlns:viewmodels="clr-namespace:HUDMerger.Core.ViewModels;assembly=HUDMerger.Core" xmlns:converters="clr-namespace:HUDMerger.Converters" mc:Ignorable="d" d:DesignHeight="240" d:DesignWidth="377" d:DataContext="{d:DesignInstance Type={x:Type viewmodels:SourceHUDPanelsListViewModel}}"> diff --git a/src/HUDMerger/Views/TargetHUDPanelsListView.xaml b/src/HUDMerger/Views/TargetHUDPanelsListView.xaml index 7773ad9..ce04caa 100644 --- a/src/HUDMerger/Views/TargetHUDPanelsListView.xaml +++ b/src/HUDMerger/Views/TargetHUDPanelsListView.xaml @@ -4,7 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:HUDMerger.Views" - xmlns:viewmodels="clr-namespace:HUDMerger.ViewModels" + xmlns:viewmodels="clr-namespace:HUDMerger.Core.ViewModels;assembly=HUDMerger.Core" xmlns:converters="clr-namespace:HUDMerger.Converters" mc:Ignorable="d" d:DesignHeight="240" d:DesignWidth="377" d:DataContext="{d:DesignInstance Type={x:Type viewmodels:TargetHUDPanelsListViewModel}}">