mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 11:56:30 +00:00
Device properties - Reworked window and merged with the debug window
This commit is contained in:
1 parent
eefc5630f3
commit
5135a8839b
17 files changed
+458
-560
No files matched your search
@@ -1,218 +0,0 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.SurfaceEditor.Dialogs.SurfaceDeviceConfigView"
|
||||
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:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:surfaceEditor="clr-namespace:Artemis.UI.Screens.SurfaceEditor.Dialogs"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance {x:Type surfaceEditor:SurfaceDeviceConfigViewModel}}">
|
||||
<UserControl.Resources>
|
||||
<shared:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
||||
</UserControl.Resources>
|
||||
<StackPanel Margin="16" Width="400">
|
||||
<!-- Title -->
|
||||
<TextBlock Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName}" Style="{StaticResource MaterialDesignHeadline6TextBlock}" />
|
||||
|
||||
<!-- Body -->
|
||||
<Grid Margin="0 25 0 0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="40" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Left side -->
|
||||
<StackPanel Grid.Column="0" Orientation="Vertical">
|
||||
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}">
|
||||
Properties
|
||||
</TextBlock>
|
||||
|
||||
<TextBox materialDesign:HintAssist.Hint="X-coordinate"
|
||||
materialDesign:TextFieldAssist.SuffixText="mm"
|
||||
Text="{Binding X, UpdateSourceTrigger=PropertyChanged}"
|
||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||
Margin="0 5" />
|
||||
<TextBox materialDesign:HintAssist.Hint="Y-coordinate"
|
||||
materialDesign:TextFieldAssist.SuffixText="mm"
|
||||
Text="{Binding Y, UpdateSourceTrigger=PropertyChanged}"
|
||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||
Margin="0 5" />
|
||||
<TextBox materialDesign:HintAssist.Hint="Scale"
|
||||
materialDesign:TextFieldAssist.SuffixText="times"
|
||||
Text="{Binding Scale, UpdateSourceTrigger=PropertyChanged}"
|
||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||
Margin="0 5" />
|
||||
<TextBox materialDesign:HintAssist.Hint="Rotation"
|
||||
materialDesign:TextFieldAssist.SuffixText="deg"
|
||||
Text="{Binding Rotation, UpdateSourceTrigger=PropertyChanged}"
|
||||
Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||
Margin="0 5 0 12" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Center divider -->
|
||||
<Rectangle Grid.Column="1" VerticalAlignment="Stretch" Fill="{StaticResource MaterialDesignTextBoxBorder}" Width="1" Margin="0 0 0 5" />
|
||||
|
||||
<!-- Right side -->
|
||||
<Grid Grid.Column="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.ColumnSpan="3" Style="{StaticResource MaterialDesignSubtitle1TextBlock}">
|
||||
Color calibration
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Style="{StaticResource MaterialDesignCaptionTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||
TextWrapping="Wrap"
|
||||
TextAlignment="Justify">
|
||||
Use the sliders below to adjust the colors of your device so that it matches your other devices.
|
||||
</TextBlock>
|
||||
|
||||
<Label Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Content="R"
|
||||
VerticalAlignment="Center" />
|
||||
<Slider Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Minimum="0"
|
||||
Maximum="200"
|
||||
ValueChanged="{s:Action ApplyScaling}"
|
||||
Value="{Binding RedScale, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="10 0"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding RedScale, StringFormat={}{0:0.0}, UpdateSourceTrigger=PropertyChanged}"
|
||||
materialDesign:TextFieldAssist.SuffixText="%"
|
||||
Width="50" />
|
||||
|
||||
<Label Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Content="G"
|
||||
VerticalAlignment="Center" />
|
||||
<Slider Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Minimum="0"
|
||||
Maximum="200"
|
||||
ValueChanged="{s:Action ApplyScaling}"
|
||||
Value="{Binding GreenScale, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="10 0"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding GreenScale, StringFormat={}{0:0.0}, UpdateSourceTrigger=PropertyChanged}"
|
||||
materialDesign:TextFieldAssist.SuffixText="%"
|
||||
Width="50" />
|
||||
|
||||
<Label Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Content="B"
|
||||
VerticalAlignment="Center" />
|
||||
<Slider Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Minimum="0"
|
||||
Maximum="200"
|
||||
ValueChanged="{s:Action ApplyScaling}"
|
||||
Value="{Binding BlueScale, UpdateSourceTrigger=PropertyChanged}"
|
||||
Margin="10 0"
|
||||
Ticks="100"
|
||||
VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding BlueScale, StringFormat={}{0:0.0}, UpdateSourceTrigger=PropertyChanged}"
|
||||
materialDesign:TextFieldAssist.SuffixText="%"
|
||||
Width="50" />
|
||||
|
||||
<Grid Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox Grid.Column="0"
|
||||
IsChecked="{Binding DisplayOnDevices}"
|
||||
Content="Show preview"
|
||||
VerticalAlignment="Center" />
|
||||
<shared:ColorPicker Grid.Column="1"
|
||||
Margin="0,0,5,0"
|
||||
HorizontalAlignment="Right"
|
||||
Color="{Binding CurrentColor, Converter={StaticResource SKColorToColorConverter}}"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<!-- Layout -->
|
||||
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}" Margin="0 25 0 0">
|
||||
Custom layout
|
||||
</TextBlock>
|
||||
<TextBlock Style="{StaticResource MaterialDesignCaptionTextBlock}"
|
||||
Foreground="{DynamicResource MaterialDesignBodyLight}"
|
||||
TextWrapping="Wrap"
|
||||
TextAlignment="Justify">
|
||||
Select a custom layout below if you want to change the appearance and/or LEDs of this device.
|
||||
</TextBlock>
|
||||
|
||||
<TextBox Style="{StaticResource MaterialDesignFloatingHintTextBox}"
|
||||
Text="{Binding Device.CustomLayoutPath}"
|
||||
VerticalAlignment="Center"
|
||||
materialDesign:TextFieldAssist.HasClearButton="True"
|
||||
IsReadOnly="True"
|
||||
PreviewMouseLeftButtonUp="{s:Action BrowseCustomLayout}">
|
||||
<materialDesign:HintAssist.Hint>
|
||||
<StackPanel Orientation="Horizontal" Margin="-2 0 0 0">
|
||||
<materialDesign:PackIcon Kind="Xml" Width="20" />
|
||||
<TextBlock>
|
||||
Layout path
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</materialDesign:HintAssist.Hint>
|
||||
</TextBox>
|
||||
|
||||
<!-- Buttons -->
|
||||
<StackPanel Orientation="Horizontal"
|
||||
HorizontalAlignment="Right">
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
||||
IsCancel="True"
|
||||
Margin="0 8 8 0"
|
||||
Command="{s:Action Cancel}">
|
||||
<Button.CommandParameter>
|
||||
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
False
|
||||
</system:Boolean>
|
||||
</Button.CommandParameter>
|
||||
CANCEL
|
||||
</Button>
|
||||
<Button Style="{StaticResource MaterialDesignFlatButton}"
|
||||
IsDefault="True"
|
||||
Margin="0 8 8 0"
|
||||
Command="{s:Action Accept}">
|
||||
<Button.CommandParameter>
|
||||
<system:Boolean xmlns:system="clr-namespace:System;assembly=mscorlib">
|
||||
True
|
||||
</system:Boolean>
|
||||
</Button.CommandParameter>
|
||||
APPLY
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -1,201 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using MaterialDesignThemes.Wpf;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using SkiaSharp;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
{
|
||||
public class SurfaceDeviceConfigViewModel : DialogViewModelBase
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly IMessageService _messageService;
|
||||
private readonly double _initialRedScale;
|
||||
private readonly double _initialGreenScale;
|
||||
private readonly double _initialBlueScale;
|
||||
private int _rotation;
|
||||
private double _scale;
|
||||
private int _x;
|
||||
private int _y;
|
||||
private double _redScale;
|
||||
private double _greenScale;
|
||||
private double _blueScale;
|
||||
private SKColor _currentColor;
|
||||
private bool _displayOnDevices;
|
||||
|
||||
public SurfaceDeviceConfigViewModel(ArtemisDevice device,
|
||||
ICoreService coreService,
|
||||
IRgbService rgbService,
|
||||
IMessageService messageService,
|
||||
IModelValidator<SurfaceDeviceConfigViewModel> validator) : base(validator)
|
||||
{
|
||||
_coreService = coreService;
|
||||
_rgbService = rgbService;
|
||||
_messageService = messageService;
|
||||
|
||||
Device = device;
|
||||
|
||||
X = (int) Device.X;
|
||||
Y = (int) Device.Y;
|
||||
Scale = Device.Scale;
|
||||
Rotation = (int) Device.Rotation;
|
||||
RedScale = Device.RedScale * 100d;
|
||||
GreenScale = Device.GreenScale * 100d;
|
||||
BlueScale = Device.BlueScale * 100d;
|
||||
//we need to store the initial values to be able to restore them when the user clicks "Cancel"
|
||||
_initialRedScale = Device.RedScale;
|
||||
_initialGreenScale = Device.GreenScale;
|
||||
_initialBlueScale = Device.BlueScale;
|
||||
CurrentColor = SKColors.White;
|
||||
_coreService.FrameRendering += OnFrameRendering;
|
||||
Device.PropertyChanged += DeviceOnPropertyChanged;
|
||||
}
|
||||
|
||||
public ArtemisDevice Device { get; }
|
||||
|
||||
public override void OnDialogClosed(object sender, DialogClosingEventArgs e)
|
||||
{
|
||||
_coreService.FrameRendering -= OnFrameRendering;
|
||||
Device.PropertyChanged -= DeviceOnPropertyChanged;
|
||||
base.OnDialogClosed(sender, e);
|
||||
}
|
||||
|
||||
public int X
|
||||
{
|
||||
get => _x;
|
||||
set => SetAndNotify(ref _x, value);
|
||||
}
|
||||
|
||||
public int Y
|
||||
{
|
||||
get => _y;
|
||||
set => SetAndNotify(ref _y, value);
|
||||
}
|
||||
|
||||
public double Scale
|
||||
{
|
||||
get => _scale;
|
||||
set => SetAndNotify(ref _scale, value);
|
||||
}
|
||||
|
||||
public int Rotation
|
||||
{
|
||||
get => _rotation;
|
||||
set => SetAndNotify(ref _rotation, value);
|
||||
}
|
||||
|
||||
public double RedScale
|
||||
{
|
||||
get => _redScale;
|
||||
set => SetAndNotify(ref _redScale, value);
|
||||
}
|
||||
|
||||
public double GreenScale
|
||||
{
|
||||
get => _greenScale;
|
||||
set => SetAndNotify(ref _greenScale, value);
|
||||
}
|
||||
|
||||
public double BlueScale
|
||||
{
|
||||
get => _blueScale;
|
||||
set => SetAndNotify(ref _blueScale, value);
|
||||
}
|
||||
|
||||
public SKColor CurrentColor
|
||||
{
|
||||
get => _currentColor;
|
||||
set => SetAndNotify(ref _currentColor, value);
|
||||
}
|
||||
|
||||
public bool DisplayOnDevices
|
||||
{
|
||||
get => _displayOnDevices;
|
||||
set => SetAndNotify(ref _displayOnDevices, value);
|
||||
}
|
||||
|
||||
public async Task Accept()
|
||||
{
|
||||
await ValidateAsync();
|
||||
if (HasErrors)
|
||||
return;
|
||||
|
||||
_coreService.ModuleRenderingDisabled = true;
|
||||
await Task.Delay(100);
|
||||
|
||||
Device.X = X;
|
||||
Device.Y = Y;
|
||||
Device.Scale = Scale;
|
||||
Device.Rotation = Rotation;
|
||||
Device.RedScale = RedScale / 100d;
|
||||
Device.GreenScale = GreenScale / 100d;
|
||||
Device.BlueScale = BlueScale / 100d;
|
||||
|
||||
_coreService.ModuleRenderingDisabled = false;
|
||||
Session.Close(true);
|
||||
}
|
||||
|
||||
public void ApplyScaling()
|
||||
{
|
||||
Device.RedScale = RedScale / 100d;
|
||||
Device.GreenScale = GreenScale / 100d;
|
||||
Device.BlueScale = BlueScale / 100d;
|
||||
}
|
||||
|
||||
public void BrowseCustomLayout(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is Button)
|
||||
{
|
||||
Device.CustomLayoutPath = null;
|
||||
_messageService.ShowMessage("Cleared imported layout");
|
||||
return;
|
||||
}
|
||||
|
||||
VistaOpenFileDialog dialog = new();
|
||||
dialog.Filter = "Layout files (*.xml)|*.xml";
|
||||
dialog.Title = "Select device layout file";
|
||||
bool? result = dialog.ShowDialog();
|
||||
if (result == true)
|
||||
{
|
||||
Device.CustomLayoutPath = dialog.FileName;
|
||||
_messageService.ShowMessage($"Imported layout from {dialog.FileName}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Cancel()
|
||||
{
|
||||
Device.RedScale = _initialRedScale;
|
||||
Device.GreenScale = _initialGreenScale;
|
||||
Device.BlueScale = _initialBlueScale;
|
||||
|
||||
base.Cancel();
|
||||
}
|
||||
|
||||
private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(Device.CustomLayoutPath))
|
||||
{
|
||||
_rgbService.ApplyBestDeviceLayout(Device);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||
{
|
||||
if (!_displayOnDevices)
|
||||
return;
|
||||
|
||||
using SKPaint overlayPaint = new()
|
||||
{
|
||||
Color = CurrentColor
|
||||
};
|
||||
e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using FluentValidation;
|
||||
|
||||
namespace Artemis.UI.Screens.SurfaceEditor.Dialogs
|
||||
{
|
||||
public class SurfaceDeviceConfigViewModelValidator : AbstractValidator<SurfaceDeviceConfigViewModel>
|
||||
{
|
||||
public SurfaceDeviceConfigViewModelValidator()
|
||||
{
|
||||
RuleFor(m => m.X).GreaterThanOrEqualTo(0).WithMessage("X-coordinate must be 0 or greater");
|
||||
|
||||
RuleFor(m => m.Y).GreaterThanOrEqualTo(0).WithMessage("Y-coordinate must be 0 or greater");
|
||||
|
||||
RuleFor(m => m.Scale).GreaterThanOrEqualTo(0.2).WithMessage("Scale must be 0.2 or greater");
|
||||
|
||||
RuleFor(m => m.Rotation).GreaterThanOrEqualTo(0).WithMessage("Rotation must be 0 or greater");
|
||||
RuleFor(m => m.Rotation).LessThanOrEqualTo(359).WithMessage("Rotation must be 359 or less");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ using System.Windows.Navigation;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Ninject.Factories;
|
||||
using Artemis.UI.Screens.Shared;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Dialogs;
|
||||
using Artemis.UI.Screens.SurfaceEditor.Visualization;
|
||||
@@ -25,8 +26,9 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IDeviceService _deviceService;
|
||||
private readonly IWindowManager _windowManager;
|
||||
private readonly IDeviceDebugVmFactory _deviceDebugVmFactory;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IInputService _inputService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private Cursor _cursor;
|
||||
@@ -39,7 +41,8 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
IDialogService dialogService,
|
||||
ISettingsService settingsService,
|
||||
IDeviceService deviceService,
|
||||
IInputService inputService)
|
||||
IWindowManager windowManager,
|
||||
IDeviceDebugVmFactory deviceDebugVmFactory)
|
||||
{
|
||||
DisplayName = "Surface Editor";
|
||||
SelectionRectangle = new RectangleGeometry();
|
||||
@@ -55,7 +58,8 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
_dialogService = dialogService;
|
||||
_settingsService = settingsService;
|
||||
_deviceService = deviceService;
|
||||
_inputService = inputService;
|
||||
_windowManager = windowManager;
|
||||
_deviceDebugVmFactory = deviceDebugVmFactory;
|
||||
}
|
||||
|
||||
public BindableCollection<SurfaceDeviceViewModel> SurfaceDeviceViewModels { get; }
|
||||
@@ -235,22 +239,14 @@ namespace Artemis.UI.Screens.SurfaceEditor
|
||||
_rgbService.SaveDevices();
|
||||
}
|
||||
|
||||
public async Task ViewProperties(ArtemisDevice device)
|
||||
public void ViewProperties(ArtemisDevice device)
|
||||
{
|
||||
object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceConfigViewModel>(
|
||||
new Dictionary<string, object> {{"device", device}}
|
||||
);
|
||||
|
||||
if ((bool) madeChanges)
|
||||
_rgbService.SaveDevice(device);
|
||||
_windowManager.ShowDialog(_deviceDebugVmFactory.DeviceDialogViewModel(device));
|
||||
}
|
||||
|
||||
public async Task DetectInput(ArtemisDevice device)
|
||||
{
|
||||
object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceDetectInputViewModel>(
|
||||
new Dictionary<string, object> {{"device", device}}
|
||||
);
|
||||
|
||||
object madeChanges = await _dialogService.ShowDialog<SurfaceDeviceDetectInputViewModel>(new Dictionary<string, object> {{"device", device}});
|
||||
if ((bool) madeChanges)
|
||||
_rgbService.SaveDevice(device);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user