diff --git a/logo/ico_512.png b/logo/ico_512.png new file mode 100644 index 00000000..34b324c1 Binary files /dev/null and b/logo/ico_512.png differ diff --git a/logo/installer_background.png b/logo/installer_background.png new file mode 100644 index 00000000..41020b31 Binary files /dev/null and b/logo/installer_background.png differ diff --git a/logo/installer_background.svg b/logo/installer_background.svg new file mode 100644 index 00000000..7024faaa --- /dev/null +++ b/logo/installer_background.svg @@ -0,0 +1,109 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/logo/installer_banner.png b/logo/installer_banner.png new file mode 100644 index 00000000..8c61a683 Binary files /dev/null and b/logo/installer_banner.png differ diff --git a/logo/installer_banner.svg b/logo/installer_banner.svg new file mode 100644 index 00000000..58144d9e --- /dev/null +++ b/logo/installer_banner.svg @@ -0,0 +1,99 @@ + + + +image/svg+xml + + + + + + + + + + + + + \ No newline at end of file diff --git a/logo/logo_512.png b/logo/logo_512.png index 0c738ef7..3a067435 100644 Binary files a/logo/logo_512.png and b/logo/logo_512.png differ diff --git a/src/AudioBand.AudioSource/AudioBand.AudioSource.csproj b/src/AudioBand.AudioSource/AudioBand.AudioSource.csproj index 2ce713ca..59cabdbe 100644 --- a/src/AudioBand.AudioSource/AudioBand.AudioSource.csproj +++ b/src/AudioBand.AudioSource/AudioBand.AudioSource.csproj @@ -46,6 +46,37 @@ prompt ..\AudioBandRules.ruleset + + true + bin\x64\Debug\ + DEBUG;TRACE + bin\Debug\AudioBand.AudioSource.xml + full + x64 + prompt + ..\AudioBandRules.ruleset + + + bin\x64\Release\ + TRACE + bin\Release\AudioBand.AudioSource.xml + true + pdbonly + x64 + prompt + ..\AudioBandRules.ruleset + + + true + bin\x64\Test\ + CODE_ANALYSIS;CODE_ANALYSIS;DEBUG;TRACE + bin\Debug\AudioBand.AudioSource.xml + full + x64 + true + prompt + ..\AudioBandRules.ruleset + diff --git a/src/AudioBand.Logging/AudioBand.Logging.csproj b/src/AudioBand.Logging/AudioBand.Logging.csproj index 2bc28b3c..6e5a9557 100644 --- a/src/AudioBand.Logging/AudioBand.Logging.csproj +++ b/src/AudioBand.Logging/AudioBand.Logging.csproj @@ -42,6 +42,34 @@ prompt ..\AudioBandRules.ruleset + + true + bin\x64\Debug\ + DEBUG;TRACE + bin\Debug\AudioBand.Logging.xml + full + x64 + prompt + ..\AudioBandRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + ..\AudioBandRules.ruleset + + + true + bin\x64\Test\ + DEBUG;TRACE + full + x64 + prompt + ..\AudioBandRules.ruleset + diff --git a/src/AudioBand.Test/AudioBand.Test.csproj b/src/AudioBand.Test/AudioBand.Test.csproj index 73136727..7331766e 100644 --- a/src/AudioBand.Test/AudioBand.Test.csproj +++ b/src/AudioBand.Test/AudioBand.Test.csproj @@ -51,6 +51,33 @@ prompt MinimumRecommendedRules.ruleset + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + true + bin\x64\Test\ + DEBUG;TRACE + full + x64 + prompt + MinimumRecommendedRules.ruleset + diff --git a/src/AudioBand.Test/AudioBandViewModelTests.cs b/src/AudioBand.Test/AudioBandViewModelTests.cs index cbe7861e..6f3adeaf 100644 --- a/src/AudioBand.Test/AudioBandViewModelTests.cs +++ b/src/AudioBand.Test/AudioBandViewModelTests.cs @@ -29,7 +29,7 @@ public void AudioBandViewModelListensToProfileChanges() _appSettings.SetupSequence(m => m.AudioBand) .Returns(first) .Returns(second); - var vm = new AudioBandViewModel(_appSettings.Object); + var vm = new AudioBandViewModel(_appSettings.Object, new Mock().Object); bool raised = false; vm.PropertyChanged += (_, __) => raised = true; diff --git a/src/AudioBand.sln b/src/AudioBand.sln index f7bc850a..34643bd1 100644 --- a/src/AudioBand.sln +++ b/src/AudioBand.sln @@ -19,58 +19,118 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioSourceHost", "AudioSou EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AudioBand.Logging", "AudioBand.Logging\AudioBand.Logging.csproj", "{D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}" EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "AudioBandInstaller", "AudioBandInstaller\AudioBandInstaller.wixproj", "{4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 Test|Any CPU = Test|Any CPU + Test|x64 = Test|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {B69832AD-8373-47AC-A52A-183238903896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B69832AD-8373-47AC-A52A-183238903896}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B69832AD-8373-47AC-A52A-183238903896}.Debug|x64.ActiveCfg = Debug|Any CPU + {B69832AD-8373-47AC-A52A-183238903896}.Debug|x64.Build.0 = Debug|Any CPU {B69832AD-8373-47AC-A52A-183238903896}.Release|Any CPU.ActiveCfg = Release|Any CPU {B69832AD-8373-47AC-A52A-183238903896}.Release|Any CPU.Build.0 = Release|Any CPU + {B69832AD-8373-47AC-A52A-183238903896}.Release|x64.ActiveCfg = Release|Any CPU + {B69832AD-8373-47AC-A52A-183238903896}.Release|x64.Build.0 = Release|Any CPU {B69832AD-8373-47AC-A52A-183238903896}.Test|Any CPU.ActiveCfg = Test|Any CPU {B69832AD-8373-47AC-A52A-183238903896}.Test|Any CPU.Build.0 = Test|Any CPU + {B69832AD-8373-47AC-A52A-183238903896}.Test|x64.ActiveCfg = Test|Any CPU + {B69832AD-8373-47AC-A52A-183238903896}.Test|x64.Build.0 = Test|Any CPU {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Debug|x64.ActiveCfg = Debug|Any CPU + {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Debug|x64.Build.0 = Debug|Any CPU {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Release|Any CPU.ActiveCfg = Release|Any CPU {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Release|Any CPU.Build.0 = Release|Any CPU + {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Release|x64.ActiveCfg = Release|Any CPU + {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Release|x64.Build.0 = Release|Any CPU {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Test|Any CPU.ActiveCfg = Test|Any CPU {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Test|Any CPU.Build.0 = Test|Any CPU + {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Test|x64.ActiveCfg = Test|Any CPU + {30F2BFEA-788A-494D-88E7-F2070528EBEA}.Test|x64.Build.0 = Test|Any CPU {43B57D81-7FAE-40D0-921E-E29F7E848288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {43B57D81-7FAE-40D0-921E-E29F7E848288}.Debug|Any CPU.Build.0 = Debug|Any CPU + {43B57D81-7FAE-40D0-921E-E29F7E848288}.Debug|x64.ActiveCfg = Debug|Any CPU + {43B57D81-7FAE-40D0-921E-E29F7E848288}.Debug|x64.Build.0 = Debug|Any CPU {43B57D81-7FAE-40D0-921E-E29F7E848288}.Release|Any CPU.ActiveCfg = Release|Any CPU {43B57D81-7FAE-40D0-921E-E29F7E848288}.Release|Any CPU.Build.0 = Release|Any CPU + {43B57D81-7FAE-40D0-921E-E29F7E848288}.Release|x64.ActiveCfg = Release|Any CPU + {43B57D81-7FAE-40D0-921E-E29F7E848288}.Release|x64.Build.0 = Release|Any CPU {43B57D81-7FAE-40D0-921E-E29F7E848288}.Test|Any CPU.ActiveCfg = Test|Any CPU + {43B57D81-7FAE-40D0-921E-E29F7E848288}.Test|x64.ActiveCfg = Test|Any CPU + {43B57D81-7FAE-40D0-921E-E29F7E848288}.Test|x64.Build.0 = Test|Any CPU {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Debug|x64.ActiveCfg = Debug|Any CPU + {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Debug|x64.Build.0 = Debug|Any CPU {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Release|Any CPU.ActiveCfg = Release|Any CPU {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Release|Any CPU.Build.0 = Release|Any CPU + {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Release|x64.ActiveCfg = Release|Any CPU + {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Release|x64.Build.0 = Release|Any CPU {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Test|Any CPU.ActiveCfg = Test|Any CPU {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Test|Any CPU.Build.0 = Test|Any CPU + {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Test|x64.ActiveCfg = Test|Any CPU + {E5E9CB59-C8CF-4042-9C13-F216153334B6}.Test|x64.Build.0 = Test|Any CPU {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Debug|x64.ActiveCfg = Debug|Any CPU + {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Debug|x64.Build.0 = Debug|Any CPU {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Release|Any CPU.ActiveCfg = Release|Any CPU {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Release|Any CPU.Build.0 = Release|Any CPU + {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Release|x64.ActiveCfg = Release|Any CPU + {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Release|x64.Build.0 = Release|Any CPU {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Test|Any CPU.ActiveCfg = Test|Any CPU + {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Test|x64.ActiveCfg = Test|Any CPU + {6D881B7B-3F3F-4613-A83F-75E31EEA5252}.Test|x64.Build.0 = Test|Any CPU {741DB79C-921D-4D91-85F1-CD10C746F46E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {741DB79C-921D-4D91-85F1-CD10C746F46E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {741DB79C-921D-4D91-85F1-CD10C746F46E}.Debug|x64.ActiveCfg = Debug|Any CPU + {741DB79C-921D-4D91-85F1-CD10C746F46E}.Debug|x64.Build.0 = Debug|Any CPU {741DB79C-921D-4D91-85F1-CD10C746F46E}.Release|Any CPU.ActiveCfg = Release|Any CPU {741DB79C-921D-4D91-85F1-CD10C746F46E}.Release|Any CPU.Build.0 = Release|Any CPU + {741DB79C-921D-4D91-85F1-CD10C746F46E}.Release|x64.ActiveCfg = Release|Any CPU + {741DB79C-921D-4D91-85F1-CD10C746F46E}.Release|x64.Build.0 = Release|Any CPU {741DB79C-921D-4D91-85F1-CD10C746F46E}.Test|Any CPU.ActiveCfg = Test|Any CPU + {741DB79C-921D-4D91-85F1-CD10C746F46E}.Test|x64.ActiveCfg = Test|Any CPU + {741DB79C-921D-4D91-85F1-CD10C746F46E}.Test|x64.Build.0 = Test|Any CPU {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Debug|x64.ActiveCfg = Debug|Any CPU + {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Debug|x64.Build.0 = Debug|Any CPU {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Release|Any CPU.ActiveCfg = Release|Any CPU {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Release|Any CPU.Build.0 = Release|Any CPU + {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Release|x64.ActiveCfg = Release|Any CPU + {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Release|x64.Build.0 = Release|Any CPU {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Test|Any CPU.ActiveCfg = Test|Any CPU {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Test|Any CPU.Build.0 = Test|Any CPU + {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Test|x64.ActiveCfg = Test|Any CPU + {D3F92C3E-E546-4A6B-ADA2-FACD95E229F7}.Test|x64.Build.0 = Test|Any CPU {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Debug|x64.ActiveCfg = Debug|Any CPU + {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Debug|x64.Build.0 = Debug|Any CPU {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Release|Any CPU.ActiveCfg = Release|Any CPU {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Release|Any CPU.Build.0 = Release|Any CPU + {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Release|x64.ActiveCfg = Release|Any CPU + {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Release|x64.Build.0 = Release|Any CPU {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Test|Any CPU.ActiveCfg = Test|Any CPU {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Test|Any CPU.Build.0 = Test|Any CPU + {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Test|x64.ActiveCfg = Test|Any CPU + {D8E1D3E5-D0AB-43C4-8AF6-60C14C5C6843}.Test|x64.Build.0 = Test|Any CPU + {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Debug|Any CPU.ActiveCfg = Debug|x64 + {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Debug|x64.ActiveCfg = Debug|x64 + {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Release|Any CPU.ActiveCfg = Release|x64 + {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Release|x64.ActiveCfg = Release|x64 + {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Release|x64.Build.0 = Release|x64 + {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Test|Any CPU.ActiveCfg = Release|x64 + {4E9EEE47-23F6-45B7-9DDB-A34731D6AE4A}.Test|x64.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/AudioBand/AudioBand.csproj b/src/AudioBand/AudioBand.csproj index d51e1dbe..5205809e 100644 --- a/src/AudioBand/AudioBand.csproj +++ b/src/AudioBand/AudioBand.csproj @@ -55,6 +55,34 @@ prompt ..\AudioBandRules.ruleset + + true + bin\x64\Debug\ + TRACE;DEBUG;DESKBAND_WPF + bin\Debug\AudioBand.xml + full + x64 + prompt + ..\AudioBandRules.ruleset + + + bin\x64\Release\ + TRACE;DESKBAND_WPF + true + pdbonly + x64 + prompt + ..\AudioBandRules.ruleset + + + true + bin\x64\Test\ + TRACE;DEBUG;DESKBAND_WPF + full + x64 + prompt + ..\AudioBandRules.ruleset + @@ -71,6 +99,7 @@ + @@ -82,6 +111,7 @@ + @@ -97,9 +127,12 @@ + + + @@ -115,7 +148,7 @@ - + @@ -149,6 +182,7 @@ + @@ -164,6 +198,7 @@ + @@ -282,6 +317,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -310,6 +349,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -358,6 +401,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/AudioBand/Behaviors/CanvasPositioning.cs b/src/AudioBand/Behaviors/CanvasPositioning.cs new file mode 100644 index 00000000..3dd81cd3 --- /dev/null +++ b/src/AudioBand/Behaviors/CanvasPositioning.cs @@ -0,0 +1,141 @@ +using System.Windows; +using System.Windows.Controls; +using AudioBand.Models; + +namespace AudioBand.Behaviors +{ + /// + /// Attached properties for changing positioning based on values. + /// + public static class CanvasPositioning + { + /// + /// Identifies the attached property. + /// + public static readonly DependencyProperty AnchorProperty + = DependencyProperty.RegisterAttached("Anchor", typeof(PositionAnchor), typeof(CanvasPositioning), new PropertyMetadata(PositionAnchor.TopLeft, AnchorPropertyChangedCallback)); + + /// + /// Identifies the attached property. + /// + public static readonly DependencyProperty AnchorXDistanceProperty + = DependencyProperty.RegisterAttached("AnchorXDistance", typeof(double), typeof(CanvasPositioning), new PropertyMetadata(0.0, AnchorXPropertyChangedCallback)); + + /// + /// Identifies the attached property. + /// + public static readonly DependencyProperty AnchorYDistanceProperty + = DependencyProperty.RegisterAttached("AnchorYDistance", typeof(double), typeof(CanvasPositioning), new PropertyMetadata(0.0, AnchorYPropertyChangedCallback)); + + /// + /// Gets the value of the property. + /// + /// The element. + /// The anchor value. + public static PositionAnchor GetAnchor(UIElement d) + { + return (PositionAnchor)d.GetValue(AnchorProperty); + } + + /// + /// Sets the value of the property. + /// + /// The element. + /// The value to set. + public static void SetAnchor(UIElement d, PositionAnchor anchor) + { + d.SetValue(AnchorProperty, anchor); + } + + /// + /// Gets the value of the property. + /// + /// The element. + /// The anchor x distance. + public static double GetAnchorXDistance(UIElement d) + { + return (double)d.GetValue(AnchorXDistanceProperty); + } + + /// + /// Sets the value of the property. + /// + /// The element. + /// The value to set. + public static void SetAnchorXDistance(UIElement d, double value) + { + d.SetValue(AnchorXDistanceProperty, value); + } + + /// + /// Gets the value of the property. + /// + /// The element. + /// The anchor y distance. + public static double GetAnchorYDistance(UIElement d) + { + return (double)d.GetValue(AnchorYDistanceProperty); + } + + /// + /// Sets the value of the property. + /// + /// The element. + /// The value to set. + public static void SetAnchorYDistance(UIElement d, double value) + { + d.SetValue(AnchorYDistanceProperty, value); + } + + private static void AnchorPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + d.SetValue(Canvas.LeftProperty, DependencyProperty.UnsetValue); + d.SetValue(Canvas.RightProperty, DependencyProperty.UnsetValue); + d.SetValue(Canvas.TopProperty, DependencyProperty.UnsetValue); + d.SetValue(Canvas.BottomProperty, DependencyProperty.UnsetValue); + + UpdateX((UIElement)d); + UpdateY((UIElement)d); + } + + private static void AnchorXPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + UpdateX((UIElement)d); + } + + private static void AnchorYPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + UpdateY((UIElement)d); + } + + private static void UpdateX(UIElement element) + { + var anchor = GetAnchor(element); + var x = GetAnchorXDistance(element); + + if (anchor.HasFlag(PositionAnchor.Left)) + { + Canvas.SetLeft(element, x); + } + else if (anchor.HasFlag(PositionAnchor.Right)) + { + Canvas.SetRight(element, x); + } + } + + private static void UpdateY(UIElement element) + { + var anchor = GetAnchor(element); + var y = GetAnchorYDistance(element); + + if (anchor.HasFlag(PositionAnchor.Top)) + { + Canvas.SetTop(element, y); + } + else if (anchor.HasFlag(PositionAnchor.Bottom)) + { + Canvas.SetBottom(element, y); + } + } + } +} diff --git a/src/AudioBand/Extensions/DescriptorIgnoreAttribute.cs b/src/AudioBand/Extensions/DescriptorIgnoreAttribute.cs new file mode 100644 index 00000000..ca82f86e --- /dev/null +++ b/src/AudioBand/Extensions/DescriptorIgnoreAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace AudioBand.Extensions +{ + /// + /// Marks enum field as ignored. + /// + [AttributeUsage(AttributeTargets.Field)] + public class DescriptorIgnoreAttribute : Attribute + { + } +} diff --git a/src/AudioBand/Extensions/EnumExtensions.cs b/src/AudioBand/Extensions/EnumExtensions.cs index 6b9c6901..cd5fb519 100644 --- a/src/AudioBand/Extensions/EnumExtensions.cs +++ b/src/AudioBand/Extensions/EnumExtensions.cs @@ -27,6 +27,7 @@ string GetDescription(FieldInfo fieldInfo) return enumType .GetFields(BindingFlags.Static | BindingFlags.Public) + .Where(field => field.GetCustomAttribute() == null) .Select(field => new EnumDescriptor((T)field.GetValue(null), GetDescription(field))); } } diff --git a/src/AudioBand/Models/AlbumArt.cs b/src/AudioBand/Models/AlbumArt.cs index 20d1b744..f488ead9 100644 --- a/src/AudioBand/Models/AlbumArt.cs +++ b/src/AudioBand/Models/AlbumArt.cs @@ -3,58 +3,19 @@ /// /// Model for the album art. /// - public class AlbumArt : ModelBase + public class AlbumArt : LayoutModelBase { - private bool _isVisible = true; - private double _width = 30; - private double _height = 30; - private double _xPosition = 245; - private double _yPosition = 0; private string _placeholderPath = ""; /// - /// Gets or sets a value indicating whether the album art is visible. + /// Initializes a new instance of the class. /// - public bool IsVisible + public AlbumArt() { - get => _isVisible; - set => SetProperty(ref _isVisible, value); - } - - /// - /// Gets or sets the width of the album art. - /// - public double Width - { - get => _width; - set => SetProperty(ref _width, value); - } - - /// - /// Gets or sets the height of the album art. - /// - public double Height - { - get => _height; - set => SetProperty(ref _height, value); - } - - /// - /// Gets or sets the x position of the album art. - /// - public double XPosition - { - get => _xPosition; - set => SetProperty(ref _xPosition, value); - } - - /// - /// Gets or sets the y position of the album art. - /// - public double YPosition - { - get => _yPosition; - set => SetProperty(ref _yPosition, value); + Width = 30; + Height = 30; + XPosition = 245; + YPosition = 0; } /// diff --git a/src/AudioBand/Models/AudioBand.cs b/src/AudioBand/Models/AudioBand.cs index 2a4426db..c6f7c634 100644 --- a/src/AudioBand/Models/AudioBand.cs +++ b/src/AudioBand/Models/AudioBand.cs @@ -1,4 +1,6 @@ -namespace AudioBand.Models +using System.Windows.Media; + +namespace AudioBand.Models { /// /// The model for the toolbar. @@ -7,6 +9,7 @@ public class AudioBand : ModelBase { private double _width = 500; private double _height = 30; + private Color _backgroundColor = Colors.Transparent; /// /// Gets or sets the width of the toolbar. @@ -25,5 +28,14 @@ public double Height get => _height; set => SetProperty(ref _height, value); } + + /// + /// Gets or sets the background color of the toolbar. + /// + public Color BackgroundColor + { + get => _backgroundColor; + set => SetProperty(ref _backgroundColor, value); + } } } diff --git a/src/AudioBand/Models/ButtonModelBase.cs b/src/AudioBand/Models/ButtonModelBase.cs index bfbaa808..1278da14 100644 --- a/src/AudioBand/Models/ButtonModelBase.cs +++ b/src/AudioBand/Models/ButtonModelBase.cs @@ -5,62 +5,12 @@ namespace AudioBand.Models /// /// Base model for buttons. /// - public class ButtonModelBase : ModelBase + public class ButtonModelBase : LayoutModelBase { - private bool _isVisible = true; - private double _width; - private double _height; - private double _xPosition; - private double _yPosition; private Color _backgroundColor = Colors.Transparent; private Color _hoveredBackgroundColor = Color.FromArgb(25, 255, 255, 255); private Color _clickedBackgroundColor = Color.FromArgb(15, 255, 255, 255); - /// - /// Gets or sets a value indicating whether the button is visible. - /// - public bool IsVisible - { - get => _isVisible; - set => SetProperty(ref _isVisible, value); - } - - /// - /// Gets or sets the width of the button. - /// - public double Width - { - get => _width; - set => SetProperty(ref _width, value); - } - - /// - /// Gets or sets the height of the button. - /// - public double Height - { - get => _height; - set => SetProperty(ref _height, value); - } - - /// - /// Gets or sets the x position of the button. - /// - public double XPosition - { - get => _xPosition; - set => SetProperty(ref _xPosition, value); - } - - /// - /// Gets or sets the y position of the button. - /// - public double YPosition - { - get => _yPosition; - set => SetProperty(ref _yPosition, value); - } - /// /// Gets or sets the background color. /// diff --git a/src/AudioBand/Models/CustomLabel.cs b/src/AudioBand/Models/CustomLabel.cs index dbf844b9..d0c21aa8 100644 --- a/src/AudioBand/Models/CustomLabel.cs +++ b/src/AudioBand/Models/CustomLabel.cs @@ -5,13 +5,8 @@ namespace AudioBand.Models /// /// Model for a custom label. /// - public class CustomLabel : ModelBase + public class CustomLabel : LayoutModelBase { - private bool _isVisible = true; - private double _width = 220; - private double _height = 15; - private double _xPosition = 0; - private double _yPosition = 0; private string _fontFamily = "Segoe UI"; private float _fontSize = 8.5f; private Color _color = Colors.White; @@ -25,6 +20,17 @@ public class CustomLabel : ModelBase private double _leftFadeOffset = 0.1; private double _rightFadeOffset = 0.9; + /// + /// Initializes a new instance of the class. + /// + public CustomLabel() + { + Width = 220; + Height = 15; + YPosition = 0; + XPosition = 0; + } + /// /// Specifies the alignment of the text in the label. /// @@ -46,51 +52,6 @@ public enum TextAlignment Center, } - /// - /// Gets or sets a value indicating whether if the label is visible. - /// - public bool IsVisible - { - get => _isVisible; - set => SetProperty(ref _isVisible, value); - } - - /// - /// Gets or sets the width of the label. - /// - public double Width - { - get => _width; - set => SetProperty(ref _width, value); - } - - /// - /// Gets or sets the height of the label. - /// - public double Height - { - get => _height; - set => SetProperty(ref _height, value); - } - - /// - /// Gets or sets the x position of the label. - /// - public double XPosition - { - get => _xPosition; - set => SetProperty(ref _xPosition, value); - } - - /// - /// Gets or sets the y position of the label. - /// - public double YPosition - { - get => _yPosition; - set => SetProperty(ref _yPosition, value); - } - /// /// Gets or sets the font family of the label. /// diff --git a/src/AudioBand/Models/LayoutModelBase.cs b/src/AudioBand/Models/LayoutModelBase.cs new file mode 100644 index 00000000..2fe85784 --- /dev/null +++ b/src/AudioBand/Models/LayoutModelBase.cs @@ -0,0 +1,69 @@ +namespace AudioBand.Models +{ + /// + /// Base model that contains support for layout. + /// + public class LayoutModelBase : ModelBase + { + private bool _isVisible = true; + private double _width; + private double _height; + private double _xPosition; + private double _yPosition; + private PositionAnchor _positionAnchor = PositionAnchor.TopLeft; + + /// + /// Gets or sets a value indicating whether it is visible. + /// + public bool IsVisible + { + get => _isVisible; + set => SetProperty(ref _isVisible, value); + } + + /// + /// Gets or sets the width. + /// + public double Width + { + get => _width; + set => SetProperty(ref _width, value); + } + + /// + /// Gets or sets the height. + /// + public double Height + { + get => _height; + set => SetProperty(ref _height, value); + } + + /// + /// Gets or sets the x position. + /// + public double XPosition + { + get => _xPosition; + set => SetProperty(ref _xPosition, value); + } + + /// + /// Gets or sets the y position. + /// + public double YPosition + { + get => _yPosition; + set => SetProperty(ref _yPosition, value); + } + + /// + /// Gets or sets the positioning. + /// + public PositionAnchor Anchor + { + get => _positionAnchor; + set => SetProperty(ref _positionAnchor, value); + } + } +} diff --git a/src/AudioBand/Models/PositionAnchor.cs b/src/AudioBand/Models/PositionAnchor.cs new file mode 100644 index 00000000..3edf4cb9 --- /dev/null +++ b/src/AudioBand/Models/PositionAnchor.cs @@ -0,0 +1,61 @@ +using System; +using System.ComponentModel; +using AudioBand.Extensions; + +namespace AudioBand.Models +{ + /// + /// Specifies the anchor behavior of the position of controls. + /// + [Flags] + public enum PositionAnchor + { + /// + /// Anchor to the top. + /// + [DescriptorIgnore] + Top = 1, + + /// + /// Anchor to the right. + /// + [DescriptorIgnore] + Right = 1 << 1, + + /// + /// Anchor to the bottom. + /// + [DescriptorIgnore] + Bottom = 1 << 2, + + /// + /// Anchor to the left. + /// + [DescriptorIgnore] + Left = 1 << 3, + + /// + /// Anchor to top left. + /// + [Description("Relative to top left")] + TopLeft = Top | Left, + + /// + /// Anchor to top right. + /// + [Description("Relative to top right")] + TopRight = Top | Right, + + /// + /// Anchor to bottom right. + /// + [Description("Relative to bottom right")] + BottomRight = Bottom | Right, + + /// + /// Anchor to bottom left. + /// + [Description("Relative to bottom left")] + BottomLeft = Bottom | Left, + } +} diff --git a/src/AudioBand/Models/PositionAnchors.cs b/src/AudioBand/Models/PositionAnchors.cs new file mode 100644 index 00000000..3a2e7d35 --- /dev/null +++ b/src/AudioBand/Models/PositionAnchors.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using AudioBand.Extensions; + +namespace AudioBand.Models +{ + /// + /// Static properties for . + /// + public static class PositionAnchors + { + /// + /// Gets the values for a . + /// + public static IEnumerable> Values { get; } = typeof(PositionAnchor).GetEnumDescriptors(); + } +} diff --git a/src/AudioBand/Models/ProgressBar.cs b/src/AudioBand/Models/ProgressBar.cs index 5b4637c0..99ae31cc 100644 --- a/src/AudioBand/Models/ProgressBar.cs +++ b/src/AudioBand/Models/ProgressBar.cs @@ -5,16 +5,22 @@ namespace AudioBand.Models /// /// Model for the progress bar. /// - public class ProgressBar : ModelBase + public class ProgressBar : LayoutModelBase { private Color _foregroundColor = Colors.DodgerBlue; private Color _backgroundColor = Colors.DimGray; private Color _hoverColor = Colors.DeepSkyBlue; - private bool _isVisible = true; - private double _xPosition = 325; - private double _yPosition = 22; - private double _width = 130; - private double _height = 4; + + /// + /// Initializes a new instance of the class. + /// + public ProgressBar() + { + Width = 130; + Height = 4; + XPosition = 325; + YPosition = 22; + } /// /// Gets or sets the foreground color. @@ -42,50 +48,5 @@ public Color HoverColor get => _hoverColor; set => SetProperty(ref _hoverColor, value); } - - /// - /// Gets or sets a value indicating whether the progress bar is visible. - /// - public bool IsVisible - { - get => _isVisible; - set => SetProperty(ref _isVisible, value); - } - - /// - /// Gets or sets the width of the progress bar. - /// - public double Width - { - get => _width; - set => SetProperty(ref _width, value); - } - - /// - /// Gets or sets the height of the progress bar. - /// - public double Height - { - get => _height; - set => SetProperty(ref _height, value); - } - - /// - /// Gets or sets the x position of the progress bar. - /// - public double XPosition - { - get => _xPosition; - set => SetProperty(ref _xPosition, value); - } - - /// - /// Gets or sets the y position of the progress bar. - /// - public double YPosition - { - get => _yPosition; - set => SetProperty(ref _yPosition, value); - } } } diff --git a/src/AudioBand/NativeMethods.cs b/src/AudioBand/NativeMethods.cs index fc53aade..056e5a4f 100644 --- a/src/AudioBand/NativeMethods.cs +++ b/src/AudioBand/NativeMethods.cs @@ -50,27 +50,35 @@ public static void SetWindowAppId(IntPtr hwnd, string appId) PROPVARIANT.ClearProp(appid); } - // Fix blur in windows 1903 causing lag by falling back to old blur behind. - public static void FixWindowComposition(Window w) + public static void DisableAcrylic(Window w) { - var win1903 = new Version(10, 0, 18362); - if (Environment.OSVersion.Version < win1903) - { - return; - } + ChangeComposition(w, AccentState.ACCENT_ENABLE_BLURBEHIND); + } - var accent = default(AccentPolicy); - accent.AccentFlags = 2; - accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; + public static void EnableAcrylic(Window w) + { + ChangeComposition(w, AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND); + } + + private static void ChangeComposition(Window w, AccentState state) + { + var accent = new AccentPolicy + { + AccentState = state, + AccentFlags = 2, + GradientColor = 0x00FFFFFF, + }; var accentStructSize = Marshal.SizeOf(accent); var accentPtr = Marshal.AllocHGlobal(accentStructSize); Marshal.StructureToPtr(accent, accentPtr, false); - var data = default(WindowCompositionAttributeData); - data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; - data.SizeOfData = accentStructSize; - data.Data = accentPtr; + var data = new WindowCompositionAttributeData + { + Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY, + SizeOfData = accentStructSize, + Data = accentPtr, + }; SetWindowCompositionAttribute(new WindowInteropHelper(w).Handle, ref data); Marshal.FreeHGlobal(accentPtr); diff --git a/src/AudioBand/Resources/ButtonStyles.xaml b/src/AudioBand/Resources/ButtonStyles.xaml index b47b1d66..8a69c0b5 100644 --- a/src/AudioBand/Resources/ButtonStyles.xaml +++ b/src/AudioBand/Resources/ButtonStyles.xaml @@ -30,7 +30,8 @@ - + @@ -85,8 +86,8 @@ - + @@ -145,7 +146,7 @@ diff --git a/src/AudioBand/Resources/ComboBoxStyles.xaml b/src/AudioBand/Resources/ComboBoxStyles.xaml index 44e51bec..a355f219 100644 --- a/src/AudioBand/Resources/ComboBoxStyles.xaml +++ b/src/AudioBand/Resources/ComboBoxStyles.xaml @@ -89,7 +89,9 @@ VerticalContentAlignment="Center" Foreground="{TemplateBinding Foreground}" Focusable="True" Background="Transparent" Visibility="Hidden" - IsReadOnly="{TemplateBinding IsReadOnly}"/> + IsReadOnly="{TemplateBinding IsReadOnly}" + ContextMenu="{StaticResource StandardInputContextMenu}"> + @@ -104,7 +106,7 @@ - + diff --git a/src/AudioBand/Resources/ContextMenuStyles.xaml b/src/AudioBand/Resources/ContextMenuStyles.xaml new file mode 100644 index 00000000..546bf264 --- /dev/null +++ b/src/AudioBand/Resources/ContextMenuStyles.xaml @@ -0,0 +1,100 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/AudioBand/Resources/NavigationPaneStyles.xaml b/src/AudioBand/Resources/NavigationPaneStyles.xaml index 7ce37b0e..6ce96978 100644 --- a/src/AudioBand/Resources/NavigationPaneStyles.xaml +++ b/src/AudioBand/Resources/NavigationPaneStyles.xaml @@ -44,7 +44,7 @@ Opacity="0" StrokeThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="{StaticResource RevealHoverLightBrush}"/> - - + + \ No newline at end of file diff --git a/src/AudioBand/Settings/AppSettings.cs b/src/AudioBand/Settings/AppSettings.cs index 22795b21..6e2b0f20 100644 --- a/src/AudioBand/Settings/AppSettings.cs +++ b/src/AudioBand/Settings/AppSettings.cs @@ -283,7 +283,7 @@ private void LoadSettingsFromPath(string path) } else { - // Check for new settings that were added to the current configuration version. + // Fix any null values var initial = new SettingsV3(); var settings = tomlFile.Get(); new MapperConfiguration(cfg => cfg.AddProfile()).CreateMapper().Map(settings, initial); diff --git a/src/AudioBand/Settings/Migrations/V2ToV3.cs b/src/AudioBand/Settings/Migrations/V2ToV3.cs index b180d1b4..21707816 100644 --- a/src/AudioBand/Settings/Migrations/V2ToV3.cs +++ b/src/AudioBand/Settings/Migrations/V2ToV3.cs @@ -28,6 +28,7 @@ private MapperConfiguration GetMapConfig() var config = new MapperConfiguration(cfg => { cfg.CreateMap() + .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft)) .ForMember(dest => dest.ScrollBehavior, opt => opt.Ignore()) .ForMember(dest => dest.TextOverflow, opt => opt.Ignore()) .ForMember(dest => dest.LeftFadeOffset, opt => opt.Ignore()) @@ -35,6 +36,7 @@ private MapperConfiguration GetMapConfig() .ForMember(dest => dest.FadeEffect, opt => opt.Ignore()); cfg.CreateMap(); cfg.CreateMap() + .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft)) .ForMember(dest => dest.Content, opt => opt.MapFrom(source => new ButtonContent())) .ForPath(dest => dest.Content.ImagePath, opt => opt.MapFrom(source => source.ImagePath)) .ForPath(dest => dest.Content.HoveredImagePath, opt => opt.MapFrom(source => source.ImagePath)) @@ -49,6 +51,7 @@ private MapperConfiguration GetMapConfig() .ForPath(dest => dest.Content.HoveredTextColor, opt => opt.Ignore()) .ForPath(dest => dest.Content.ClickedTextColor, opt => opt.Ignore()); cfg.CreateMap() + .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft)) .ForMember(dest => dest.Content, opt => opt.MapFrom(source => new ButtonContent())) .ForPath(dest => dest.Content.ImagePath, opt => opt.MapFrom(source => source.ImagePath)) .ForPath(dest => dest.Content.HoveredImagePath, opt => opt.MapFrom(source => source.ImagePath)) @@ -63,6 +66,7 @@ private MapperConfiguration GetMapConfig() .ForPath(dest => dest.Content.HoveredTextColor, opt => opt.Ignore()) .ForPath(dest => dest.Content.ClickedTextColor, opt => opt.Ignore()); cfg.CreateMap() + .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft)) .ForMember(dest => dest.BackgroundColor, opt => opt.Ignore()) .ForMember(dest => dest.HoveredBackgroundColor, opt => opt.Ignore()) .ForMember(dest => dest.ClickedBackgroundColor, opt => opt.Ignore()) @@ -87,7 +91,12 @@ private MapperConfiguration GetMapConfig() .ForPath(dest => dest.PauseContent.HoveredTextColor, opt => opt.Ignore()) .ForPath(dest => dest.PauseContent.ClickedTextColor, opt => opt.Ignore()); cfg.CreateMap() + .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft)) .ForMember(dest => dest.HoverColor, opt => opt.Ignore()); + cfg.CreateMap() + .ForMember(dest => dest.BackgroundColor, opt => opt.Ignore()); + cfg.CreateMap() + .ForMember(dest => dest.Anchor, opt => opt.MapFrom(source => PositionAnchor.TopLeft)); cfg.CreateMap() .ForMember(dest => dest.AlbumArtPopupSettings, opt => opt.MapFrom(source => source.AlbumArtPopupSettings)) .ForMember(dest => dest.AlbumArtSettings, opt => opt.MapFrom(source => source.AlbumArtSettings)) diff --git a/src/AudioBand/Settings/Profiles/SettingsV3Profile.cs b/src/AudioBand/Settings/Profiles/SettingsV3Profile.cs index ad7abe8e..95beb86a 100644 --- a/src/AudioBand/Settings/Profiles/SettingsV3Profile.cs +++ b/src/AudioBand/Settings/Profiles/SettingsV3Profile.cs @@ -1,11 +1,12 @@ -using AudioBand.Models; +using System.Collections.Generic; +using AudioBand.Models; using AudioBand.Settings.Models.v3; using AutoMapper; namespace AudioBand.Settings.Profiles { /// - /// Fixes new values that are added to the configuration. + /// Fixes null settings. /// internal class SettingsV3Profile : Profile { @@ -16,7 +17,15 @@ public SettingsV3Profile() { CreateMap(); CreateMap() - .ForMember(dest => dest.RepeatModeButtonSettings, opt => opt.NullSubstitute(new RepeatModeButton())) // Repeat mode button was added after + .ForMember(dest => dest.AlbumArtPopupSettings, opt => opt.NullSubstitute(new AlbumArtPopup())) + .ForMember(dest => dest.AlbumArtSettings, opt => opt.NullSubstitute(new AlbumArt())) + .ForMember(dest => dest.AudioBandSettings, opt => opt.NullSubstitute(new AudioBand.Models.AudioBand())) + .ForMember(dest => dest.CustomLabelSettings, opt => opt.NullSubstitute(new List())) + .ForMember(dest => dest.NextButtonSettings, opt => opt.NullSubstitute(new NextButton())) + .ForMember(dest => dest.PlayPauseButtonSettings, opt => opt.NullSubstitute(new PlayPauseButton())) + .ForMember(dest => dest.PreviousButtonSettings, opt => opt.NullSubstitute(new PreviousButton())) + .ForMember(dest => dest.ProgressBarSettings, opt => opt.NullSubstitute(new ProgressBar())) + .ForMember(dest => dest.RepeatModeButtonSettings, opt => opt.NullSubstitute(new RepeatModeButton())) .ForMember(dest => dest.ShuffleModeButtonSettings, opt => opt.NullSubstitute(new ShuffleModeButton())); } } diff --git a/src/AudioBand/ValueConverters/Converters.cs b/src/AudioBand/ValueConverters/Converters.cs index bab95d5e..9344ba01 100644 --- a/src/AudioBand/ValueConverters/Converters.cs +++ b/src/AudioBand/ValueConverters/Converters.cs @@ -1,4 +1,6 @@ -namespace AudioBand.ValueConverters +using System.Windows.Data; + +namespace AudioBand.ValueConverters { /// /// Static class that contains converts. @@ -69,5 +71,15 @@ public static class Converters /// Gets a . /// public static EmptyStringToBoolConverter EmptyStringToBool { get; } = new EmptyStringToBoolConverter(); + + /// + /// Gets a brush to color converter. + /// + public static IValueConverter BrushToColor { get; } = new ReverseConverter(new ColorToBrushConverter()); + + /// + /// Gets a . + /// + public static FlagToBoolConverter HasFlag { get; } = new FlagToBoolConverter(); } } diff --git a/src/AudioBand/ValueConverters/FlagToBoolConverter.cs b/src/AudioBand/ValueConverters/FlagToBoolConverter.cs new file mode 100644 index 00000000..9c25bf0b --- /dev/null +++ b/src/AudioBand/ValueConverters/FlagToBoolConverter.cs @@ -0,0 +1,31 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Data; + +namespace AudioBand.ValueConverters +{ + /// + /// Converts enum flag to bool. + /// + [ValueConversion(typeof(Enum), typeof(bool))] + public class FlagToBoolConverter : IValueConverter + { + /// + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null || value == DependencyProperty.UnsetValue || parameter == null) + { + return false; + } + + return ((Enum)value).HasFlag((Enum)parameter); + } + + /// + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/AudioBand/ValueConverters/ReverseConverter.cs b/src/AudioBand/ValueConverters/ReverseConverter.cs index 6d94db94..29078e74 100644 --- a/src/AudioBand/ValueConverters/ReverseConverter.cs +++ b/src/AudioBand/ValueConverters/ReverseConverter.cs @@ -12,21 +12,27 @@ namespace AudioBand.ValueConverters [ContentProperty("Converter")] public class ReverseConverter : IValueConverter { + private readonly IValueConverter _converter; + /// - /// Gets or sets he converter to revrse. + /// Initializes a new instance of the class with the converter to reverse. /// - public IValueConverter Converter { get; set; } + /// The converter to reverse. + public ReverseConverter(IValueConverter converter) + { + _converter = converter; + } /// public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return Converter.ConvertBack(value, targetType, parameter, culture); + return _converter.ConvertBack(value, targetType, parameter, culture); } /// public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - return Converter.Convert(value, targetType, parameter, culture); + return _converter.Convert(value, targetType, parameter, culture); } } } diff --git a/src/AudioBand/ValueConverters/TimeSpanToMsConverter.cs b/src/AudioBand/ValueConverters/TimeSpanToMsConverter.cs index 871755e0..25a7530e 100644 --- a/src/AudioBand/ValueConverters/TimeSpanToMsConverter.cs +++ b/src/AudioBand/ValueConverters/TimeSpanToMsConverter.cs @@ -1,5 +1,6 @@ using System; using System.Globalization; +using System.Windows; using System.Windows.Data; namespace AudioBand.ValueConverters @@ -13,12 +14,22 @@ public class TimeSpanToMsConverter : IValueConverter /// public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { + if (value == null || value == DependencyProperty.UnsetValue) + { + return 0; + } + return ((TimeSpan)value).TotalMilliseconds; } /// public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { + if (value == null || value == DependencyProperty.UnsetValue) + { + return TimeSpan.Zero; + } + return TimeSpan.FromMilliseconds((double)value); } } diff --git a/src/AudioBand/ViewModels/AboutDialogViewModel.cs b/src/AudioBand/ViewModels/AboutDialogViewModel.cs index 75edd71e..fd9b4974 100644 --- a/src/AudioBand/ViewModels/AboutDialogViewModel.cs +++ b/src/AudioBand/ViewModels/AboutDialogViewModel.cs @@ -1,5 +1,8 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; +using System.IO; using System.Reflection; +using System.Windows.Input; using AudioBand.Commands; namespace AudioBand.ViewModels @@ -9,14 +12,6 @@ namespace AudioBand.ViewModels /// public class AboutDialogViewModel : ViewModelBase { - /// - /// Initializes a new instance of the class. - /// - public AboutDialogViewModel() - { - OpenLinkCommand = new RelayCommand(OpenLinkCommandOnExecute); - } - /// /// Gets the current audioband version. /// @@ -40,9 +35,29 @@ public AboutDialogViewModel() /// /// Gets the command to open the link to the project. /// - public RelayCommand OpenLinkCommand { get; } + public ICommand OpenLinkCommand { get; } = new RelayCommand(OpenLinkCommandOnExecute); + + /// + /// Gets the command to open the settings folder. + /// + public ICommand OpenSettingsFolderCommand { get; } = new RelayCommand(OpenSettingsFolderCommandOnExecute); + + /// + /// Gets the command to open the audioband logs. + /// + public ICommand OpenLog { get; } = new RelayCommand(OpenLogCommandOnExecute); + + private static void OpenLogCommandOnExecute(object obj) + { + Process.Start(Path.Combine(Path.GetTempPath(), "AudioBand.log")); + } + + private static void OpenSettingsFolderCommandOnExecute(object obj) + { + Process.Start(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AudioBand")); + } - private void OpenLinkCommandOnExecute(string link) + private static void OpenLinkCommandOnExecute(string link) { Process.Start(link); } diff --git a/src/AudioBand/ViewModels/AlbumArtViewModel.cs b/src/AudioBand/ViewModels/AlbumArtViewModel.cs index 3ad6bdfa..50c9453d 100644 --- a/src/AudioBand/ViewModels/AlbumArtViewModel.cs +++ b/src/AudioBand/ViewModels/AlbumArtViewModel.cs @@ -12,7 +12,7 @@ namespace AudioBand.ViewModels /// /// View model for the album art. /// - public class AlbumArtViewModel : ViewModelBase + public class AlbumArtViewModel : LayoutViewModelBase { private readonly IAppSettings _appsettings; private IAudioSource _audioSource; @@ -32,56 +32,6 @@ public AlbumArtViewModel(IAppSettings appsettings, IDialogService dialogService) appsettings.ProfileChanged += AppsettingsOnProfileChanged; } - /// - /// Gets or sets a value indicating whether it is visible. - /// - [PropertyChangeBinding(nameof(Models.AlbumArt.IsVisible))] - public bool IsVisible - { - get => Model.IsVisible; - set => SetProperty(nameof(Model.IsVisible), value); - } - - /// - /// Gets or sets the width. - /// - [PropertyChangeBinding(nameof(Models.AlbumArt.Width))] - public double Width - { - get => Model.Width; - set => SetProperty(nameof(Model.Width), value); - } - - /// - /// Gets or sets the height. - /// - [PropertyChangeBinding(nameof(Models.AlbumArt.Height))] - public double Height - { - get => Model.Height; - set => SetProperty(nameof(Model.Height), value); - } - - /// - /// Gets or sets the x position. - /// - [PropertyChangeBinding(nameof(Models.AlbumArt.XPosition))] - public double XPosition - { - get => Model.XPosition; - set => SetProperty(nameof(Model.XPosition), value); - } - - /// - /// Gets or sets the y position. - /// - [PropertyChangeBinding(nameof(Models.AlbumArt.YPosition))] - public double YPosition - { - get => Model.YPosition; - set => SetProperty(nameof(Model.YPosition), value); - } - /// /// Gets or sets the placeholder path. /// diff --git a/src/AudioBand/ViewModels/AudioBandViewModel.cs b/src/AudioBand/ViewModels/AudioBandViewModel.cs index a127feb4..f31efca6 100644 --- a/src/AudioBand/ViewModels/AudioBandViewModel.cs +++ b/src/AudioBand/ViewModels/AudioBandViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Windows.Media; using AudioBand.Settings; namespace AudioBand.ViewModels @@ -15,9 +16,11 @@ public class AudioBandViewModel : ViewModelBase /// Initializes a new instance of the class. /// /// The app settings. - public AudioBandViewModel(IAppSettings appsettings) + /// The dialog service. + public AudioBandViewModel(IAppSettings appsettings, IDialogService dialogService) : base(appsettings.AudioBand) { + DialogService = dialogService; _appsettings = appsettings; appsettings.ProfileChanged += AppsettingsOnProfileChanged; } @@ -42,6 +45,21 @@ public double Height set => SetProperty(nameof(Model.Height), value); } + /// + /// Gets or sets the background color. + /// + [PropertyChangeBinding(nameof(Models.AudioBand.BackgroundColor))] + public Color BackgroundColor + { + get => Model.BackgroundColor; + set => SetProperty(nameof(Model.BackgroundColor), value); + } + + /// + /// Gets the dialog service. + /// + public IDialogService DialogService { get; } + private void AppsettingsOnProfileChanged(object sender, EventArgs e) { Debug.Assert(IsEditing == false, "Should not be editing"); diff --git a/src/AudioBand/ViewModels/ButtonViewModelBase.cs b/src/AudioBand/ViewModels/ButtonViewModelBase.cs index 9d61bc30..69ff8944 100644 --- a/src/AudioBand/ViewModels/ButtonViewModelBase.cs +++ b/src/AudioBand/ViewModels/ButtonViewModelBase.cs @@ -10,7 +10,7 @@ namespace AudioBand.ViewModels /// Base view model for buttons. /// /// The button model. - public class ButtonViewModelBase : ViewModelBase + public class ButtonViewModelBase : LayoutViewModelBase where TButton : ButtonModelBase, new() { private readonly List _contentViewModels = new List(); @@ -26,56 +26,6 @@ public ButtonViewModelBase(TButton model, IDialogService dialogService) DialogService = dialogService; } - /// - /// Gets or sets a value indicating whether the button is visible. - /// - [PropertyChangeBinding(nameof(ButtonModelBase.IsVisible))] - public bool IsVisible - { - get => Model.IsVisible; - set => SetProperty(nameof(Model.IsVisible), value); - } - - /// - /// Gets or sets the width. - /// - [PropertyChangeBinding(nameof(ButtonModelBase.Width))] - public double Width - { - get => Model.Width; - set => SetProperty(nameof(Model.Width), value); - } - - /// - /// Gets or sets the height. - /// - [PropertyChangeBinding(nameof(ButtonModelBase.Height))] - public double Height - { - get => Model.Height; - set => SetProperty(nameof(Model.Height), value); - } - - /// - /// Gets or sets the x position. - /// - [PropertyChangeBinding(nameof(ButtonModelBase.XPosition))] - public double XPosition - { - get => Model.XPosition; - set => SetProperty(nameof(Model.XPosition), value); - } - - /// - /// Gets or sets the y position. - /// - [PropertyChangeBinding(nameof(ButtonModelBase.YPosition))] - public double YPosition - { - get => Model.YPosition; - set => SetProperty(nameof(Model.YPosition), value); - } - /// /// Gets or sets the background color. /// diff --git a/src/AudioBand/ViewModels/CustomLabelViewModel.cs b/src/AudioBand/ViewModels/CustomLabelViewModel.cs index ad601917..b759bf80 100644 --- a/src/AudioBand/ViewModels/CustomLabelViewModel.cs +++ b/src/AudioBand/ViewModels/CustomLabelViewModel.cs @@ -13,7 +13,7 @@ namespace AudioBand.ViewModels /// /// The view model for a custom label. /// - public class CustomLabelViewModel : ViewModelBase + public class CustomLabelViewModel : LayoutViewModelBase { private readonly FormattedTextParser _parser; private IAudioSource _audioSource; @@ -92,56 +92,6 @@ public TextAlignment TextAlignment set => SetProperty(nameof(Model.Alignment), value); } - /// - /// Gets or sets a value indicating whether the text is visible. - /// - [PropertyChangeBinding(nameof(CustomLabel.IsVisible))] - public bool IsVisible - { - get => Model.IsVisible; - set => SetProperty(nameof(Model.IsVisible), value); - } - - /// - /// Gets or sets the width. - /// - [PropertyChangeBinding(nameof(CustomLabel.Width))] - public double Width - { - get => Model.Width; - set => SetProperty(nameof(Model.Width), value); - } - - /// - /// Gets or sets the height. - /// - [PropertyChangeBinding(nameof(CustomLabel.Height))] - public double Height - { - get => Model.Height; - set => SetProperty(nameof(Model.Height), value); - } - - /// - /// Gets or sets the x position. - /// - [PropertyChangeBinding(nameof(CustomLabel.XPosition))] - public double XPosition - { - get => Model.XPosition; - set => SetProperty(nameof(Model.XPosition), value); - } - - /// - /// Gets or sets the y position. - /// - [PropertyChangeBinding(nameof(CustomLabel.YPosition))] - public double YPosition - { - get => Model.YPosition; - set => SetProperty(nameof(Model.YPosition), value); - } - /// /// Gets or sets the scroll speed. /// diff --git a/src/AudioBand/ViewModels/LayoutViewModelBase.cs b/src/AudioBand/ViewModels/LayoutViewModelBase.cs new file mode 100644 index 00000000..e0bdaec0 --- /dev/null +++ b/src/AudioBand/ViewModels/LayoutViewModelBase.cs @@ -0,0 +1,81 @@ +using AudioBand.Models; + +namespace AudioBand.ViewModels +{ + /// + /// Base view model for . + /// + /// A object. + public class LayoutViewModelBase : ViewModelBase + where TModel : LayoutModelBase, new() + { + /// + /// Initializes a new instance of the class. + /// + /// The model. + public LayoutViewModelBase(TModel model) + : base(model) + { + } + + /// + /// Gets or sets a value indicating whether it is visible. + /// + [PropertyChangeBinding(nameof(LayoutModelBase.IsVisible))] + public bool IsVisible + { + get => Model.IsVisible; + set => SetProperty(nameof(Model.IsVisible), value); + } + + /// + /// Gets or sets the width. + /// + [PropertyChangeBinding(nameof(LayoutModelBase.Width))] + public double Width + { + get => Model.Width; + set => SetProperty(nameof(Model.Width), value); + } + + /// + /// Gets or sets the height. + /// + [PropertyChangeBinding(nameof(LayoutModelBase.Height))] + public double Height + { + get => Model.Height; + set => SetProperty(nameof(Model.Height), value); + } + + /// + /// Gets or sets the x position. + /// + [PropertyChangeBinding(nameof(LayoutModelBase.XPosition))] + public double XPosition + { + get => Model.XPosition; + set => SetProperty(nameof(Model.XPosition), value); + } + + /// + /// Gets or sets the y position. + /// + [PropertyChangeBinding(nameof(LayoutModelBase.YPosition))] + public double YPosition + { + get => Model.YPosition; + set => SetProperty(nameof(Model.YPosition), value); + } + + /// + /// Gets or sets the relative positioning. + /// + [PropertyChangeBinding(nameof(LayoutModelBase.Anchor))] + public PositionAnchor Anchor + { + get => Model.Anchor; + set => SetProperty(nameof(Model.Anchor), value); + } + } +} diff --git a/src/AudioBand/ViewModels/ProgressBarViewModel.cs b/src/AudioBand/ViewModels/ProgressBarViewModel.cs index 1adbd736..8a9bae66 100644 --- a/src/AudioBand/ViewModels/ProgressBarViewModel.cs +++ b/src/AudioBand/ViewModels/ProgressBarViewModel.cs @@ -1,11 +1,7 @@ using System; using System.Diagnostics; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Input; using System.Windows.Media; using AudioBand.AudioSource; -using AudioBand.Commands; using AudioBand.Models; using AudioBand.Settings; @@ -14,7 +10,7 @@ namespace AudioBand.ViewModels /// /// View model for the progress bar. /// - public class ProgressBarViewModel : ViewModelBase + public class ProgressBarViewModel : LayoutViewModelBase { private readonly IAppSettings _appsettings; private IAudioSource _audioSource; @@ -65,58 +61,6 @@ public Color HoverColor set => SetProperty(nameof(Model.HoverColor), value); } - /// - /// Gets or sets a value indicating whether the bar is visible. - /// - [PropertyChangeBinding(nameof(ProgressBar.IsVisible))] - public bool IsVisible - { - get => Model.IsVisible; - set => SetProperty(nameof(Model.IsVisible), value); - } - - /// - /// Gets or sets the width. - /// - [PropertyChangeBinding(nameof(ProgressBar.Width))] - [AlsoNotify(nameof(Size))] - public double Width - { - get => Model.Width; - set => SetProperty(nameof(Model.Width), value); - } - - /// - /// Gets or sets the height. - /// - [PropertyChangeBinding(nameof(ProgressBar.Height))] - [AlsoNotify(nameof(Size))] - public double Height - { - get => Model.Height; - set => SetProperty(nameof(Model.Height), value); - } - - /// - /// Gets or sets the x position. - /// - [PropertyChangeBinding(nameof(ProgressBar.XPosition))] - public double XPosition - { - get => Model.XPosition; - set => SetProperty(nameof(Model.XPosition), value); - } - - /// - /// Gets or sets the y position. - /// - [PropertyChangeBinding(nameof(ProgressBar.YPosition))] - public double YPosition - { - get => Model.YPosition; - set => SetProperty(nameof(Model.YPosition), value); - } - /// /// Gets or sets the track progress. /// diff --git a/src/AudioBand/Views/AudioBandToolbar.xaml b/src/AudioBand/Views/AudioBandToolbar.xaml index 9266da40..5d658bbb 100644 --- a/src/AudioBand/Views/AudioBandToolbar.xaml +++ b/src/AudioBand/Views/AudioBandToolbar.xaml @@ -12,9 +12,10 @@ xmlns:resources="clr-namespace:AudioBand.Resources" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:models="clr-namespace:AudioBand.Models" + xmlns:views="clr-namespace:AudioBand.Views" mc:Ignorable="d" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" - Background="Transparent" + Background="{Binding ViewModels.AudioBandViewModel.BackgroundColor, Converter={x:Static converters:Converters.ColorToBrush}}" d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance viewModels:AudioBandToolbarViewModel, IsDesignTimeCreatable=False}"> @@ -116,11 +117,13 @@ + RenderOptions.BitmapScalingMode="Fant" + behaviors:CanvasPositioning.Anchor="{Binding Anchor}" + behaviors:CanvasPositioning.AnchorXDistance="{Binding XPosition}" + behaviors:CanvasPositioning.AnchorYDistance="{Binding YPosition}"> diff --git a/src/AudioBand/Views/AudioBandToolbar.xaml.cs b/src/AudioBand/Views/AudioBandToolbar.xaml.cs index 681493db..4200872e 100644 --- a/src/AudioBand/Views/AudioBandToolbar.xaml.cs +++ b/src/AudioBand/Views/AudioBandToolbar.xaml.cs @@ -33,6 +33,7 @@ private void OnSizeChanged(object sender, SizeChangedEventArgs e) var deskbandSize = new DeskBandSize((int)Math.Round(ActualWidth * scale), (int)Math.Round(ActualHeight * scale)); _options.MinHorizontalSize = deskbandSize; _options.HorizontalSize = deskbandSize; + _options.MaxHorizontalHeight = deskbandSize.Height; } } } diff --git a/src/AudioBand/Views/Dialogs/AboutDialog.xaml b/src/AudioBand/Views/Dialogs/AboutDialog.xaml index 6e3c5efc..0802041b 100644 --- a/src/AudioBand/Views/Dialogs/AboutDialog.xaml +++ b/src/AudioBand/Views/Dialogs/AboutDialog.xaml @@ -89,7 +89,16 @@ - + + + + + + + + + +