Core - Streamlined public parts of profile creation

UI - Started adjusting the VMs for the layer refactor
This commit is contained in:
Robert authored and SpoinkyNL committed 2020-09-12 10:39:44 +02:00
1 parent 12ac50226f
commit 3e75f200f4
58 files changed
+694 -1196

No files matched your search

@@ -1,60 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.Visualization.ProfileDeviceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:visualization1="clr-namespace:Artemis.UI.Screens.ProfileEditor.Visualization"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type visualization1:ProfileDeviceViewModel}}">
<UserControl.Resources>
<converters:NullToImageConverter x:Key="NullToImageConverter" />
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
</UserControl.Resources>
<Grid Width="{Binding Device.RgbDevice.ActualSize.Width}" Height="{Binding Device.RgbDevice.ActualSize.Height}">
<Grid.RenderTransform>
<RotateTransform Angle="{Binding Device.Rotation}" />
</Grid.RenderTransform>
<!-- Device image with fallback -->
<Image VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Source="{Binding Device.RgbDevice.DeviceInfo.Image, Converter={StaticResource NullToImageConverter}}" />
<Rectangle Fill="{DynamicResource MaterialDesignCardBackground}"
Stroke="{DynamicResource MaterialDesignTextBoxBorder}"
Margin="-5"
StrokeThickness="1"
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}"
Visibility="{Binding Device.RgbDevice.DeviceInfo.Image, ConverterParameter=Inverted, Converter={StaticResource NullToVisibilityConverter}}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextWrapping="Wrap"
TextAlignment="Center" />
<!-- LEDs -->
<ItemsControl ItemsSource="{Binding Leds}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="{x:Type ContentPresenter}">
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Width="{Binding Width}" Height="{Binding Height}" s:View.Model="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</UserControl>
@@ -1,96 +0,0 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using Artemis.Core;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.Visualization
{
public class ProfileDeviceViewModel : CanvasViewModel
{
private bool _addedLeds;
private ArtemisDevice _device;
private ObservableCollection<ProfileLedViewModel> _leds;
public ProfileDeviceViewModel(ArtemisDevice device)
{
Device = device;
Leds = new ObservableCollection<ProfileLedViewModel>();
Task.Run(AddLedsAsync);
}
public ObservableCollection<ProfileLedViewModel> Leds
{
get => _leds;
set => SetAndNotify(ref _leds, value);
}
public ArtemisDevice Device
{
get => _device;
set => SetAndNotify(ref _device, value);
}
public bool AddedLeds
{
get => _addedLeds;
private set => SetAndNotify(ref _addedLeds, value);
}
public new double X
{
get => Device.X;
set => Device.X = value;
}
public new double Y
{
get => Device.Y;
set => Device.Y = value;
}
public int ZIndex
{
get => Device.ZIndex;
set => Device.ZIndex = value;
}
public Rect DeviceRectangle => Device.RgbDevice == null
? new Rect()
: new Rect(X, Y, Device.RgbDevice.Size.Width, Device.RgbDevice.Size.Height);
/// <summary>
/// Update the color of all LEDs if finished adding
/// </summary>
public void Update()
{
if (!AddedLeds)
return;
foreach (var ledViewModel in Leds)
ledViewModel.Update();
}
/// <summary>
/// Adds LEDs in batches of 5 to avoid UI freezes
/// </summary>
/// <returns></returns>
private async Task AddLedsAsync()
{
var index = 0;
foreach (var led in Device.Leds.ToList())
{
Execute.OnUIThreadSync(() => Leds.Add(new ProfileLedViewModel(led)));
if (index % 5 == 0)
await Task.Delay(1);
index++;
}
AddedLeds = true;
}
}
}
@@ -1,93 +0,0 @@
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.Visualization.ProfileLedView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:visualization1="clr-namespace:Artemis.UI.Screens.ProfileEditor.Visualization"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance {x:Type visualization1:ProfileLedViewModel}}"
d:DesignHeight="25" d:DesignWidth="25">
<UserControl.Resources>
<converters:NullToImageConverter x:Key="NullToImageConverter" />
<Style TargetType="{x:Type Path}" x:Key="DimStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDimmed}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Shape.Opacity)" To="0.2" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Shape.Opacity)" To="1" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<Canvas Width="{Binding Led.RgbLed.ActualSize.Width, Mode=OneWay}" Height="{Binding Led.RgbLed.ActualSize.Height, Mode=OneWay}">
<Canvas.Background>
<ImageBrush AlignmentX="Center" AlignmentY="Center" Stretch="Fill"
ImageSource="{Binding Led.RgbLed.Image, Converter={StaticResource NullToImageConverter}, Mode=OneWay}" />
</Canvas.Background>
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" Style="{StaticResource DimStyle}">
<Path.Fill>
<SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" Opacity="0.333" />
</Path.Fill>
</Path>
<Path Data="{Binding StrokeGeometry, Mode=OneWay}" ClipToBounds="False" Style="{StaticResource DimStyle}">
<Path.Fill>
<SolidColorBrush Color="{Binding DisplayColor, Mode=OneWay}" />
</Path.Fill>
</Path>
<!-- Selection -->
<Path Data="{Binding DisplayGeometry, Mode=OneWay}" ClipToBounds="False" StrokeThickness="1" StrokeLineJoin="Round">
<Path.Style>
<Style TargetType="{x:Type Path}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="ToSelected">
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="{StaticResource Accent700}" Duration="0:0:0.25" />
<ColorAnimation
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
To="{StaticResource Accent400}" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)"
To="Transparent" Duration="0:0:0.25" />
<ColorAnimation
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)"
To="Transparent" Duration="0:0:0.25" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
<Path.Fill>
<SolidColorBrush Opacity="0.25" />
</Path.Fill>
<Path.Stroke>
<SolidColorBrush Opacity="0.5" />
</Path.Stroke>
</Path>
</Canvas>
</UserControl>
@@ -1,148 +0,0 @@
using System;
using System.Windows;
using System.Windows.Media;
using Artemis.Core;
using Artemis.UI.Extensions;
using RGB.NET.Core;
using Stylet;
using Color = System.Windows.Media.Color;
namespace Artemis.UI.Screens.ProfileEditor.Visualization
{
public class ProfileLedViewModel : PropertyChangedBase
{
private Color _displayColor;
private Geometry _displayGeometry;
private bool _isDimmed;
private bool _isSelected;
private Geometry _strokeGeometry;
public ProfileLedViewModel(ArtemisLed led)
{
Led = led;
// Don't want ActualLocation here since rotation is done in XAML
X = led.RgbLed.Location.X * led.RgbLed.Device.Scale.Horizontal;
Y = led.RgbLed.Location.Y * led.RgbLed.Device.Scale.Vertical;
Width = led.RgbLed.ActualSize.Width;
Height = led.RgbLed.ActualSize.Height;
Execute.PostToUIThread(CreateLedGeometry);
}
public ArtemisLed Led { get; }
public double X { get; }
public double Y { get; }
public double Width { get; }
public double Height { get; }
public bool IsSelected
{
get => _isSelected;
set => SetAndNotify(ref _isSelected, value);
}
public bool IsDimmed
{
get => _isDimmed;
set => SetAndNotify(ref _isDimmed, value);
}
public Geometry DisplayGeometry
{
get => _displayGeometry;
private set => SetAndNotify(ref _displayGeometry, value);
}
public Geometry StrokeGeometry
{
get => _strokeGeometry;
private set => SetAndNotify(ref _strokeGeometry, value);
}
public Color DisplayColor
{
get => _displayColor;
private set => SetAndNotify(ref _displayColor, value);
}
public void Update()
{
var newColor = Led.RgbLed.Color.ToMediaColor();
Execute.PostToUIThread(() =>
{
if (!DisplayColor.Equals(newColor))
DisplayColor = newColor;
});
}
private void CreateLedGeometry()
{
switch (Led.RgbLed.Shape)
{
case Shape.Custom:
if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
CreateCustomGeometry(2.0);
else
CreateCustomGeometry(1.0);
break;
case Shape.Rectangle:
if (Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keyboard || Led.RgbLed.Device.DeviceInfo.DeviceType == RGBDeviceType.Keypad)
CreateKeyCapGeometry();
else
CreateRectangleGeometry();
break;
case Shape.Circle:
CreateCircleGeometry();
break;
default:
throw new ArgumentOutOfRangeException();
}
// Stroke geometry is the display geometry excluding the inner geometry
StrokeGeometry = DisplayGeometry.GetWidenedPathGeometry(new Pen(null, 1.0), 0.1, ToleranceType.Absolute);
DisplayGeometry.Freeze();
StrokeGeometry.Freeze();
}
private void CreateRectangleGeometry()
{
DisplayGeometry = new RectangleGeometry(new Rect(0.5, 0.5, Width - 1, Height - 1));
}
private void CreateCircleGeometry()
{
DisplayGeometry = new EllipseGeometry(new Rect(0.5, 0.5, Width - 1, Height - 1));
}
private void CreateKeyCapGeometry()
{
DisplayGeometry = new RectangleGeometry(new Rect(1, 1, Width - 2, Height - 2), 1.6, 1.6);
}
private void CreateCustomGeometry(double deflateAmount)
{
try
{
DisplayGeometry = Geometry.Combine(
Geometry.Empty,
Geometry.Parse(Led.RgbLed.ShapeData),
GeometryCombineMode.Union,
new TransformGroup
{
Children = new TransformCollection
{
new ScaleTransform(Width - deflateAmount, Height - deflateAmount),
new TranslateTransform(deflateAmount / 2, deflateAmount / 2)
}
}
);
}
catch (Exception)
{
CreateRectangleGeometry();
}
}
}
}
@@ -15,7 +15,7 @@ using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.Visualization
{
public class ProfileViewModel : ProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
public class ProfileViewModel : Screen, IProfileEditorPanelViewModel, IHandle<MainWindowFocusChangedEvent>, IHandle<MainWindowKeyEvent>
{
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileLayerVmFactory _profileLayerVmFactory;