Added tons of UI-stuff (working configuration and visualization for all providers)

This commit is contained in:
DarthAffe committed 2017-08-12 19:19:25 +02:00
1 parent 111cc52e71
commit 427d42f1bb
25 files changed
+951 -62

No files matched your search

@@ -0,0 +1,29 @@
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
xmlns:controls="clr-namespace:KeyboardAudioVisualizer.Controls"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<styles:CachedResourceDictionary.MergedDictionaries>
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/FrameworkElement.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Theme.xaml" />
</styles:CachedResourceDictionary.MergedDictionaries>
<DataTemplate DataType="{x:Type visualizationProvider:BeatVisualizationProviderConfiguration}">
<Grid>
<Grid.Resources>
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
</Grid.Resources>
<controls:Formular LabelWidth="240">
<Label controls:Formular.IsLabel="True" Content="No configuration available ..." />
</controls:Formular>
</Grid>
</DataTemplate>
</styles:CachedResourceDictionary>
@@ -1,20 +1,33 @@
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
xmlns:visualizationPRovider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
xmlns:controls="clr-namespace:KeyboardAudioVisualizer.Controls">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
xmlns:controls="clr-namespace:KeyboardAudioVisualizer.Controls"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<styles:CachedResourceDictionary.MergedDictionaries>
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/FrameworkElement.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Theme.xaml" />
</styles:CachedResourceDictionary.MergedDictionaries>
<DataTemplate DataType="{x:Type visualizationPRovider:FrequencyBarsVisualizationProviderConfiguration}">
<DataTemplate DataType="{x:Type visualizationProvider:FrequencyBarsVisualizationProviderConfiguration}">
<Grid>
<Grid.Resources>
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
<ObjectDataProvider x:Key="SpectrumModes" MethodName="GetValues" ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="visualizationProvider:SpectrumMode"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="ValueModes" MethodName="GetValues" ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="visualizationProvider:ValueMode"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Grid.Resources>
<Grid.ColumnDefinitions>
@@ -26,12 +39,48 @@
</Grid.ColumnDefinitions>
<controls:Formular Grid.Column="0">
</controls:Formular>
<Label controls:Formular.IsLabel="True" Content="Spectrum:" />
<ComboBox controls:Formular.Fill="True"
ItemsSource="{Binding Source={StaticResource SpectrumModes}}"
SelectedItem="{Binding SpectrumMode}"/>
<controls:Formular Grid.Column="1">
<Label controls:Formular.IsLabel="True" Content="Value:" />
<ComboBox controls:Formular.Fill="True"
ItemsSource="{Binding Source={StaticResource ValueModes}}"
SelectedItem="{Binding ValueMode}"/>
<Label controls:Formular.IsLabel="True" Content="Bars:" />
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="96" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="BottomRight"
Value="{Binding Bars}" />
</controls:Formular>
<controls:Formular Grid.Column="2">
<Label controls:Formular.IsLabel="True" Content="Min Freq.:" />
<Slider controls:Formular.Fill="True" Minimum="0" Maximum="22100" IsSnapToTickEnabled="True" TickFrequency="10" TickPlacement="None"
Value="{Binding MinFrequency}" />
<Label controls:Formular.IsLabel="True" Content="Max Freq.:" />
<Slider controls:Formular.Fill="True" Minimum="0" Maximum="22100" IsSnapToTickEnabled="True" TickFrequency="10" TickPlacement="None"
Value="{Binding MaxFrequency}" />
<Label controls:Formular.IsLabel="True" Content="Gamma:" />
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="6" IsSnapToTickEnabled="True" TickFrequency="0.25" TickPlacement="BottomRight"
IsEnabled="{Binding SpectrumMode, Converter={StaticResource EqualsToBoolConverter}, ConverterParameter={x:Static visualizationProvider:SpectrumMode.Gamma}}"
Value="{Binding Gamma}" />
</controls:Formular>
<controls:Formular Grid.Column="4">
<Label controls:Formular.IsLabel="True" controls:Formular.LineBreaks="1" Content="Reference:" />
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="240" IsSnapToTickEnabled="True" TickFrequency="1" TickPlacement="None"
Value="{Binding ReferenceLevel}" />
<Label controls:Formular.IsLabel="True" controls:Formular.LineBreaks="1" Content="Smoothing:" />
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="10" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
Value="{Binding Smoothing}" />
<Label controls:Formular.IsLabel="True" controls:Formular.LineBreaks="1" Content="Emphasize:" />
<Slider controls:Formular.Fill="True" Minimum="0" Maximum="2" IsSnapToTickEnabled="True" TickFrequency="0.05" TickPlacement="BottomRight"
Value="{Binding EmphasisePeaks}" />
</controls:Formular>
</Grid>
</DataTemplate>
@@ -0,0 +1,57 @@
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
xmlns:controls="clr-namespace:KeyboardAudioVisualizer.Controls"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<styles:CachedResourceDictionary.MergedDictionaries>
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/FrameworkElement.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Theme.xaml" />
</styles:CachedResourceDictionary.MergedDictionaries>
<DataTemplate DataType="{x:Type visualizationProvider:LevelVisualizationProviderConfiguration}">
<Grid>
<Grid.Resources>
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
<ObjectDataProvider x:Key="ConversionModes" MethodName="GetValues" ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="visualizationProvider:ConversionMode"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<controls:Formular Grid.Column="0">
<Label controls:Formular.IsLabel="True" Content="Calculation:" />
<ComboBox controls:Formular.Fill="True"
ItemsSource="{Binding Source={StaticResource ConversionModes}}"
SelectedItem="{Binding ConversionMode}"/>
</controls:Formular>
<controls:Formular Grid.Column="2">
<Label controls:Formular.IsLabel="True" Content="Scale:" />
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="10" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
Value="{Binding Scale}" />
</controls:Formular>
<controls:Formular Grid.Column="4">
<Label controls:Formular.IsLabel="True" controls:Formular.LineBreaks="1" Content="Smoothing:" />
<Slider controls:Formular.Fill="True" Minimum="1" Maximum="10" IsSnapToTickEnabled="True" TickFrequency="0.5" TickPlacement="BottomRight"
Value="{Binding Smoothing}" />
</controls:Formular>
</Grid>
</DataTemplate>
</styles:CachedResourceDictionary>
@@ -19,6 +19,11 @@
<styles:CachedResourceDictionary.MergedDictionaries>
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Navigation.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/UI/Configuration/FrequencyBarsConfiguration.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/UI/Visualization/FrequencyBarsVisualization.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/UI/Configuration/LevelConfiguration.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/UI/Visualization/LevelVisualization.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/UI/Configuration/BeatConfiguration.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/UI/Visualization/BeatVisualization.xaml" />
</styles:CachedResourceDictionary.MergedDictionaries>
</styles:CachedResourceDictionary>
</controls:BlurredDecorationWindow.Resources>
@@ -28,9 +33,26 @@
</controls:BlurredDecorationWindow.DataContext>
<TabControl Style="{StaticResource StyleTabControlNavigation}">
<TabItem Header="Primary">
<TabItem Header="Keyboard">
<DockPanel>
<GroupBox DockPanel.Dock="Top">
<controls:Formular>
<controls:Formular.Resources>
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
</controls:Formular.Resources>
<Label controls:Formular.IsLabel="True" Content="Visualization: " />
<ComboBox controls:Formular.Fill="True" SelectedIndex="0">
<ComboBox.Items>
<ComboBoxItem>Frequency Bars</ComboBoxItem>
</ComboBox.Items>
</ComboBox>
</controls:Formular>
</GroupBox>
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=PrimaryVisualizationProvider.Configuration}" />
</GroupBox>
@@ -40,18 +62,64 @@
</DockPanel>
</TabItem>
<TabItem Header="Secondary">
<DockPanel>
<TabItem Header="Mouse/Headset">
<DockPanel LastChildFill="False">
<GroupBox DockPanel.Dock="Top">
<controls:Formular>
<controls:Formular.Resources>
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
</controls:Formular.Resources>
<Label controls:Formular.IsLabel="True" Content="Visualization: " />
<ComboBox controls:Formular.Fill="True" SelectedIndex="0">
<ComboBox.Items>
<ComboBoxItem>Beat-Detection</ComboBoxItem>
</ComboBox.Items>
</ComboBox>
</controls:Formular>
</GroupBox>
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=SecondaryVisualizationProvider.Configuration}" />
</GroupBox>
<GroupBox Margin="0,8,0,0">
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=SecondaryVisualizationProvider}" />
</GroupBox>
</DockPanel>
</TabItem>
<TabItem Header="Lightbar/Mousemate">
<DockPanel LastChildFill="False">
<GroupBox DockPanel.Dock="Top">
<controls:Formular>
<controls:Formular.Resources>
<Style BasedOn="{StaticResource StyleLabelFormular}" TargetType="Label" />
<Style BasedOn="{StaticResource StyleTextBlockFormular}" TargetType="TextBlock" />
<Style BasedOn="{StaticResource StyleListBoxFormular}" TargetType="ListBox" />
</controls:Formular.Resources>
<Label controls:Formular.IsLabel="True" Content="Visualization: " />
<ComboBox controls:Formular.Fill="True" SelectedIndex="0">
<ComboBox.Items>
<ComboBoxItem>Level</ComboBoxItem>
</ComboBox.Items>
</ComboBox>
</controls:Formular>
</GroupBox>
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=TertiaryVisualizationProvider.Configuration}" />
</GroupBox>
<GroupBox Margin="0,8,0,0" DockPanel.Dock="Top">
<ContentControl Content="{Binding Source={x:Static audioProcessing:AudioProcessor.Instance}, Path=TertiaryVisualizationProvider}" />
</GroupBox>
</DockPanel>
</TabItem>
<TabItem Header="Settings">
<GroupBox VerticalAlignment="Top">
<StackPanel Orientation="Vertical">
@@ -65,11 +133,11 @@
<Label controls:Formular.IsLabel="True" Content="Version:" />
<TextBlock Text="{Binding Version}" />
<Label controls:Formular.LineBreaks="1" controls:Formular.IsLabel="True" Content="Connected Devices:" />
<Label controls:Formular.LineBreaks="1" controls:Formular.IsLabel="True" Content="Devices:" />
</controls:Formular>
<!-- TODO DarthAffe 05.08.2017: Fix the formular to support that use-case -->
<ItemsControl VerticalAlignment="Top" HorizontalAlignment="Left" Margin="168,-22,0,0" ItemsSource="{Binding Source={x:Static core:RGBSurface.Instance}, Path=Devices}">
<ItemsControl VerticalAlignment="Top" HorizontalAlignment="Left" Margin="120,-22,0,0" ItemsSource="{Binding Source={x:Static core:RGBSurface.Instance}, Path=Devices}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Style="{StaticResource StyleTextBlockFormular}">
@@ -0,0 +1,32 @@
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
xmlns:visualization="clr-namespace:KeyboardAudioVisualizer.UI.Visualization">
<styles:CachedResourceDictionary.MergedDictionaries>
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/FrameworkElement.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Theme.xaml" />
</styles:CachedResourceDictionary.MergedDictionaries>
<Style x:Key="StyleBeatVisualizer"
BasedOn="{StaticResource StyleFrameworkElement}"
TargetType="{x:Type visualization:BeatVisualizer}">
<Setter Property="Height" Value="64" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type visualization:BeatVisualizer}">
<Border Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Brush}"
Opacity="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BeatValue}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate DataType="{x:Type visualizationProvider:BeatVisualizationProvider}">
<visualization:BeatVisualizer Style="{StaticResource StyleBeatVisualizer}" VisualizationProvider="{Binding}" />
</DataTemplate>
</styles:CachedResourceDictionary>
@@ -0,0 +1,80 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
using RGB.NET.Core;
using Color = System.Windows.Media.Color;
using Point = System.Windows.Point;
namespace KeyboardAudioVisualizer.UI.Visualization
{
public class BeatVisualizer : Control
{
#region DependencyProperties
// ReSharper disable InconsistentNaming
public static readonly DependencyProperty VisualizationProviderProperty = DependencyProperty.Register(
"VisualizationProvider", typeof(IVisualizationProvider), typeof(BeatVisualizer), new PropertyMetadata(default(IVisualizationProvider)));
public IVisualizationProvider VisualizationProvider
{
get => (IVisualizationProvider)GetValue(VisualizationProviderProperty);
set => SetValue(VisualizationProviderProperty, value);
}
public static readonly DependencyProperty BrushProperty = DependencyProperty.Register(
"Brush", typeof(Brush), typeof(BeatVisualizer), new PropertyMetadata(default(Brush)));
public Brush Brush
{
get => (Brush)GetValue(BrushProperty);
set => SetValue(BrushProperty, value);
}
public static readonly DependencyProperty BeatValueProperty = DependencyProperty.Register(
"BeatValue", typeof(float), typeof(BeatVisualizer), new PropertyMetadata(default(float)));
public float BeatValue
{
get => (float)GetValue(BeatValueProperty);
set => SetValue(BeatValueProperty, value);
}
// ReSharper restore InconsistentNaming
#endregion
#region Constructors
public BeatVisualizer()
{
RGBSurface.Instance.Updated += args => Dispatcher.BeginInvoke(new Action(Update), DispatcherPriority.Normal);
//TODO DarthAffe 12.08.2017: Create brush from config
Brush = new SolidColorBrush(Color.FromRgb(255, 255, 255));
}
#endregion
#region Methods
private void Update()
{
IVisualizationProvider visualizationProvider = VisualizationProvider;
if ((visualizationProvider == null) || (Visibility != Visibility.Visible)) return;
if (visualizationProvider.VisualizationData[0] > 0.9)
BeatValue = 1f;
else if (BeatValue > 0.01f)
{
float newValue = BeatValue * 0.625f;
if (newValue > 0.01f)
BeatValue = newValue;
else BeatValue = 0;
}
}
#endregion
}
}
@@ -0,0 +1,32 @@
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
xmlns:visualization="clr-namespace:KeyboardAudioVisualizer.UI.Visualization">
<styles:CachedResourceDictionary.MergedDictionaries>
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/FrameworkElement.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Theme.xaml" />
</styles:CachedResourceDictionary.MergedDictionaries>
<Style x:Key="StyleFrequencyBarsVisualizer"
BasedOn="{StaticResource StyleFrameworkElement}"
TargetType="{x:Type visualization:FrequencyBarsVisualizer}">
<Setter Property="SnapsToDevicePixels" Value="False" />
<Setter Property="UseLayoutRounding" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type visualization:FrequencyBarsVisualizer}">
<StackPanel x:Name="PART_BarsPanel" Orientation="Horizontal" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate DataType="{x:Type visualizationProvider:FrequencyBarsVisualizationProvider}">
<visualization:FrequencyBarsVisualizer Style="{StaticResource StyleFrequencyBarsVisualizer}" VisualizationProvider="{Binding}" />
</DataTemplate>
</styles:CachedResourceDictionary>
@@ -0,0 +1,142 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
using RGB.NET.Brushes.Gradients;
using RGB.NET.Core;
using Color = System.Windows.Media.Color;
using Rectangle = System.Windows.Shapes.Rectangle;
namespace KeyboardAudioVisualizer.UI.Visualization
{
[TemplatePart(Name = "PART_BarsPanel", Type = typeof(Panel))]
public class FrequencyBarsVisualizer : Control
{
#region DependencyProperties
// ReSharper disable InconsistentNaming
public static readonly DependencyProperty VisualizationProviderProperty = DependencyProperty.Register(
"VisualizationProvider", typeof(IVisualizationProvider), typeof(FrequencyBarsVisualizer),
new PropertyMetadata(default(IVisualizationProvider), VisualizationProviderChanged));
public IVisualizationProvider VisualizationProvider
{
get => (IVisualizationProvider)GetValue(VisualizationProviderProperty);
set => SetValue(VisualizationProviderProperty, value);
}
// ReSharper restore InconsistentNaming
#endregion
#region Properties & Fields
private IGradient _gradient;
private Panel _panel;
private Rectangle[] _bars = new Rectangle[0];
#endregion
#region Constructors
public FrequencyBarsVisualizer()
{
RGBSurface.Instance.Updated += args => Dispatcher.BeginInvoke(new Action(Update), DispatcherPriority.Normal);
SizeChanged += (sender, args) => UpdateSizes();
//TODO DarthAffe 12.08.2017: Get gradient from config
_gradient = new RainbowGradient(300, -14);
}
#endregion
#region Methods
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_panel = GetTemplateChild("PART_BarsPanel") as Panel;
InitializeBars();
}
private static void VisualizationProviderChanged(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
FrequencyBarsVisualizer visualizer = dependencyObject as FrequencyBarsVisualizer;
if (visualizer == null) return;
void ConfigurationOnPropertyChanged(object sender, PropertyChangedEventArgs args) => visualizer.ConfigurationChanged(args.PropertyName);
if (dependencyPropertyChangedEventArgs.OldValue is IVisualizationProvider oldVisualizationProvider)
oldVisualizationProvider.Configuration.PropertyChanged -= ConfigurationOnPropertyChanged;
if (dependencyPropertyChangedEventArgs.NewValue is IVisualizationProvider newVisualizationProvider)
newVisualizationProvider.Configuration.PropertyChanged += ConfigurationOnPropertyChanged;
}
private void ConfigurationChanged(string changedPropertyName)
{
if ((changedPropertyName == null) || (changedPropertyName == nameof(FrequencyBarsVisualizationProviderConfiguration.Bars)))
InitializeBars();
}
private void InitializeBars()
{
if (_panel == null) return;
_panel.Children.Clear();
_bars = new Rectangle[((FrequencyBarsVisualizationProviderConfiguration)VisualizationProvider.Configuration).Bars];
for (int i = 0; i < _bars.Length; i++)
{
_bars[i] = new Rectangle { VerticalAlignment = VerticalAlignment.Bottom, Width = 0 };
_panel.Children.Add(_bars[i]);
}
UpdateSizes();
UpdateColors();
}
private void UpdateSizes()
{
if (_bars.Length == 0) return;
double barSpacing = ActualWidth / _bars.Length;
double barWidth = (barSpacing * 3.0) / 4.0;
double margin = barSpacing - barWidth;
for (int i = 0; i < _bars.Length; i++)
{
_bars[i].Width = barWidth;
_bars[i].Margin = new Thickness(margin / 2, 0, margin / 2, 0);
}
}
private void UpdateColors()
{
for (int i = 0; i < _bars.Length; i++)
{
RGB.NET.Core.Color color = _gradient.GetColor((double)i / _bars.Length);
_bars[i].Fill = new SolidColorBrush(Color.FromRgb(color.R, color.G, color.B));
}
}
private void Update()
{
IVisualizationProvider visualizationProvider = VisualizationProvider;
if ((visualizationProvider == null) || (Visibility != Visibility.Visible)) return;
int count = Math.Min(_bars.Length, visualizationProvider.VisualizationData.Length);
for (int i = 0; i < count; i++)
{
_bars[i].Height = (float)((_bars[i].Height * 0.5) + ((ActualHeight * visualizationProvider.VisualizationData[i]) * (1.0 - 0.5)));
if (double.IsNaN(_bars[i].Height)) _bars[i].Height = 0;
}
}
#endregion
}
}
@@ -0,0 +1,70 @@
<styles:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="clr-namespace:KeyboardAudioVisualizer.Styles"
xmlns:visualizationProvider="clr-namespace:KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider"
xmlns:visualization="clr-namespace:KeyboardAudioVisualizer.UI.Visualization">
<styles:CachedResourceDictionary.MergedDictionaries>
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/FrameworkElement.xaml" />
<styles:CachedResourceDictionary Source="/KeyboardAudioVisualizer;component/Styles/Theme.xaml" />
</styles:CachedResourceDictionary.MergedDictionaries>
<Style x:Key="StyleLevelVisualizer"
BasedOn="{StaticResource StyleFrameworkElement}"
TargetType="{x:Type visualization:LevelVisualizer}">
<Setter Property="Height" Value="64" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type visualization:LevelVisualizer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderThickness="0,0,1,0" BorderBrush="White">
<Border x:Name="BrdLeft" Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BrushLeft}">
<Border.OpacityMask>
<VisualBrush>
<VisualBrush.Visual>
<Border Width="{Binding ElementName=BrdLeft, Path=ActualWidth}"
Height="{Binding ElementName=BrdLeft, Path=ActualHeight}"
Background="Transparent">
<Rectangle HorizontalAlignment="Right" Fill="Black"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SizeLeft}" />
</Border>
</VisualBrush.Visual>
</VisualBrush>
</Border.OpacityMask>
</Border>
</Border>
<Border Grid.Column="1" BorderThickness="1,0,0,0" BorderBrush="White">
<Border x:Name="BrdRight" Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BrushRight}">
<Border.OpacityMask>
<VisualBrush>
<VisualBrush.Visual>
<Border Width="{Binding ElementName=BrdRight, Path=ActualWidth}"
Height="{Binding ElementName=BrdRight, Path=ActualHeight}"
Background="Transparent">
<Rectangle HorizontalAlignment="Left" Fill="Black"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SizeRight}" />
</Border>
</VisualBrush.Visual>
</VisualBrush>
</Border.OpacityMask>
</Border>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate DataType="{x:Type visualizationProvider:LevelVisualizationProvider}">
<visualization:LevelVisualizer Style="{StaticResource StyleLevelVisualizer}" VisualizationProvider="{Binding}" />
</DataTemplate>
</styles:CachedResourceDictionary>
@@ -0,0 +1,97 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using KeyboardAudioVisualizer.AudioProcessing.VisualizationProvider;
using RGB.NET.Core;
using Color = System.Windows.Media.Color;
using Point = System.Windows.Point;
namespace KeyboardAudioVisualizer.UI.Visualization
{
public class LevelVisualizer : Control
{
#region DependencyProperties
// ReSharper disable InconsistentNaming
public static readonly DependencyProperty VisualizationProviderProperty = DependencyProperty.Register(
"VisualizationProvider", typeof(IVisualizationProvider), typeof(LevelVisualizer), new PropertyMetadata(default(IVisualizationProvider)));
public IVisualizationProvider VisualizationProvider
{
get => (IVisualizationProvider)GetValue(VisualizationProviderProperty);
set => SetValue(VisualizationProviderProperty, value);
}
public static readonly DependencyProperty BrushLeftProperty = DependencyProperty.Register(
"BrushLeft", typeof(Brush), typeof(LevelVisualizer), new PropertyMetadata(default(Brush)));
public Brush BrushLeft
{
get => (Brush)GetValue(BrushLeftProperty);
set => SetValue(BrushLeftProperty, value);
}
public static readonly DependencyProperty BrushRightProperty = DependencyProperty.Register(
"BrushRight", typeof(Brush), typeof(LevelVisualizer), new PropertyMetadata(default(Brush)));
public Brush BrushRight
{
get => (Brush)GetValue(BrushRightProperty);
set => SetValue(BrushRightProperty, value);
}
public static readonly DependencyProperty SizeLeftProperty = DependencyProperty.Register(
"SizeLeft", typeof(int), typeof(LevelVisualizer), new PropertyMetadata(default(int)));
public int SizeLeft
{
get => (int)GetValue(SizeLeftProperty);
set => SetValue(SizeLeftProperty, value);
}
public static readonly DependencyProperty SizeRightProperty = DependencyProperty.Register(
"SizeRight", typeof(int), typeof(LevelVisualizer), new PropertyMetadata(default(int)));
public int SizeRight
{
get => (int)GetValue(SizeRightProperty);
set => SetValue(SizeRightProperty, value);
}
// ReSharper restore InconsistentNaming
#endregion
#region Constructors
public LevelVisualizer()
{
RGBSurface.Instance.Updated += args => Dispatcher.BeginInvoke(new Action(Update), DispatcherPriority.Normal);
//TODO DarthAffe 12.08.2017: Create brush from config
BrushLeft = new LinearGradientBrush(Color.FromRgb(255, 0, 0), Color.FromRgb(0, 0, 255), new Point(0, 0.5), new Point(1, 0.5));
BrushRight = new LinearGradientBrush(Color.FromRgb(0, 0, 255), Color.FromRgb(255, 0, 0), new Point(0, 0.5), new Point(1, 0.5));
}
#endregion
#region Methods
private void Update()
{
IVisualizationProvider visualizationProvider = VisualizationProvider;
if ((visualizationProvider == null) || (Visibility != Visibility.Visible)) return;
int horizontalSizeLeft = (int)(visualizationProvider.VisualizationData[0] * (ActualWidth / 2));
if (Math.Abs(SizeLeft - horizontalSizeLeft) > 1)
SizeLeft = horizontalSizeLeft;
int horizontalSizeRight = (int)(visualizationProvider.VisualizationData[1] * (ActualWidth / 2));
if (Math.Abs(SizeRight - horizontalSizeRight) > 1)
SizeRight = horizontalSizeRight;
}
#endregion
}
}