Core - Allow device providers to opt out of layout LED creation/removal

Device properties UI - Highlight selected LEDs in white
This commit is contained in:
Robert committed 2021-04-01 19:57:28 +02:00
1 parent 7000110dcb
commit 7a3be83bf6
11 files changed
+206 -101

No files matched your search

@@ -105,8 +105,8 @@
</VisualBrush>
</Grid.Background>
<!-- No need to provide LEDs to highlight as LEDs are already physically highlighted -->
<shared:DeviceVisualizer Device="{Binding Device}"
HighlightedLeds="{Binding SelectedLeds}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ShowColors="True"
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Input;
using System.Xml.Serialization;
using Artemis.Core;
using Artemis.Core.Services;
@@ -13,20 +13,28 @@ using Artemis.UI.Shared.Services;
using MaterialDesignThemes.Wpf;
using Ookii.Dialogs.Wpf;
using RGB.NET.Layout;
using SkiaSharp;
using Stylet;
namespace Artemis.UI.Screens.Settings.Device
{
public class DeviceDialogViewModel : Conductor<Screen>.Collection.OneActive
{
private readonly ICoreService _coreService;
private readonly IDeviceService _deviceService;
private readonly IDialogService _dialogService;
private readonly IRgbService _rgbService;
private ArtemisLed _selectedLed;
private SnackbarMessageQueue _deviceMessageQueue;
private BindableCollection<ArtemisLed> _selectedLeds;
public DeviceDialogViewModel(ArtemisDevice device, IDeviceService deviceService, IRgbService rgbService, IDialogService dialogService, IDeviceDebugVmFactory factory)
public DeviceDialogViewModel(ArtemisDevice device,
ICoreService coreService,
IDeviceService deviceService,
IRgbService rgbService,
IDialogService dialogService,
IDeviceDebugVmFactory factory)
{
_coreService = coreService;
_deviceService = deviceService;
_rgbService = rgbService;
_dialogService = dialogService;
@@ -39,19 +47,8 @@ namespace Artemis.UI.Screens.Settings.Device
Items.Add(factory.DeviceLedsTabViewModel(device));
ActiveItem = Items.First();
DisplayName = $"{device.RgbDevice.DeviceInfo.Model} | Artemis";
}
protected override void OnInitialActivate()
{
DeviceMessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(5));
Device.DeviceUpdated += DeviceOnDeviceUpdated;
base.OnInitialActivate();
}
protected override void OnClose()
{
Device.DeviceUpdated -= DeviceOnDeviceUpdated;
base.OnClose();
SelectedLeds = new BindableCollection<ArtemisLed>();
}
public ArtemisDevice Device { get; }
@@ -63,29 +60,61 @@ namespace Artemis.UI.Screens.Settings.Device
set => SetAndNotify(ref _deviceMessageQueue, value);
}
public ArtemisLed SelectedLed
{
get => _selectedLed;
set
{
if (!SetAndNotify(ref _selectedLed, value)) return;
NotifyOfPropertyChange(nameof(SelectedLeds));
}
}
public bool CanExportLayout => Device.Layout?.IsValid ?? false;
public List<ArtemisLed> SelectedLeds => SelectedLed != null ? new List<ArtemisLed> {SelectedLed} : null;
public BindableCollection<ArtemisLed> SelectedLeds
{
get => _selectedLeds;
set => SetAndNotify(ref _selectedLeds, value);
}
public bool CanOpenImageDirectory => Device.Layout?.Image != null;
public void OnLedClicked(object sender, LedClickedEventArgs e)
{
if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift))
SelectedLeds.Clear();
SelectedLeds.Add(e.Led);
}
protected override void OnInitialActivate()
{
_coreService.FrameRendering += CoreServiceOnFrameRendering;
DeviceMessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(5));
Device.DeviceUpdated += DeviceOnDeviceUpdated;
base.OnInitialActivate();
}
protected override void OnClose()
{
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
Device.DeviceUpdated -= DeviceOnDeviceUpdated;
base.OnClose();
}
private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e)
{
if (SelectedLeds == null)
return;
using SKPaint highlightPaint = new() {Color = SKColors.White};
using SKPaint dimPaint = new() {Color = new SKColor(0, 0, 0, 192)};
foreach (ArtemisLed artemisLed in Device.Leds)
e.Canvas.DrawRect(artemisLed.AbsoluteRectangle, SelectedLeds.Contains(artemisLed) ? highlightPaint : dimPaint);
}
private void DeviceOnDeviceUpdated(object sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(CanExportLayout));
}
// ReSharper disable UnusedMember.Global
#region Command handlers
public void ClearSelection()
{
SelectedLed = null;
SelectedLeds.Clear();
}
public void IdentifyDevice()
@@ -190,19 +219,5 @@ namespace Artemis.UI.Screens.Settings.Device
#endregion
// ReSharper restore UnusedMember.Global
#region Event handlers
private void DeviceOnDeviceUpdated(object sender, EventArgs e)
{
NotifyOfPropertyChange(nameof(CanExportLayout));
}
public void OnLedClicked(object sender, LedClickedEventArgs e)
{
SelectedLed = e.Led;
}
#endregion
}
}
@@ -4,34 +4,39 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
xmlns:tabs="clr-namespace:Artemis.UI.Screens.Settings.Device.Tabs"
xmlns:Converters="clr-namespace:Artemis.UI.Converters" x:Class="Artemis.UI.Screens.Settings.Device.Tabs.DeviceLedsTabView"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
x:Class="Artemis.UI.Screens.Settings.Device.Tabs.DeviceLedsTabView"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type tabs:DeviceLedsTabViewModel}}">
<UserControl.Resources>
<Converters:UriToFileNameConverter x:Key="UriToFileNameConverter"/>
<converters:UriToFileNameConverter x:Key="UriToFileNameConverter"/>
</UserControl.Resources>
<Grid>
<DataGrid ItemsSource="{Binding Device.Leds}"
d:DataContext="{d:DesignInstance Type={x:Type core:ArtemisLed}}"
<DataGrid ItemsSource="{Binding LedViewModels}"
d:DataContext="{d:DesignInstance Type={x:Type tabs:DeviceLedsTabLedViewModel}}"
CanUserSortColumns="True"
IsReadOnly="True"
CanUserAddRows="False"
AutoGenerateColumns="False"
materialDesign:DataGridAssist.CellPadding="5"
materialDesign:DataGridAssist.ColumnHeaderPadding="5"
SelectedItem="{Binding Parent.SelectedLed}"
CanUserResizeRows="False"
VirtualizingStackPanel.VirtualizationMode="Standard"
Margin="10">
<DataGrid.Resources>
<Style TargetType="DataGridRow" BasedOn="{StaticResource MaterialDesignDataGridRow}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<materialDesign:DataGridTextColumn Binding="{Binding RgbLed.Id}" Header="LED ID" Width="Auto" />
<materialDesign:DataGridTextColumn Binding="{Binding RgbLed.Color}" Header="Color (ARGB)" Width="Auto" />
<materialDesign:DataGridTextColumn Binding="{Binding Layout.Image, Converter={StaticResource UriToFileNameConverter}, Mode=OneWay}" Header="Image file" />
<materialDesign:DataGridTextColumn Binding="{Binding RgbLed.Shape}" Header="Shape" />
<materialDesign:DataGridTextColumn Binding="{Binding RgbLed.Size}" Header="Size" Width="Auto" />
<materialDesign:DataGridTextColumn Binding="{Binding RgbLed.CustomData}" Header="LED data" Width="Auto" />
<materialDesign:DataGridTextColumn Binding="{Binding ArtemisLed.RgbLed.Id}" Header="LED ID" Width="Auto" />
<materialDesign:DataGridTextColumn Binding="{Binding ArtemisLed.RgbLed.Color}" Header="Color (ARGB)" Width="Auto" />
<materialDesign:DataGridTextColumn Binding="{Binding ArtemisLed.Layout.Image, Converter={StaticResource UriToFileNameConverter}, Mode=OneWay}" Header="Image file" />
<materialDesign:DataGridTextColumn Binding="{Binding ArtemisLed.RgbLed.Shape}" Header="Shape" />
<materialDesign:DataGridTextColumn Binding="{Binding ArtemisLed.RgbLed.Size}" Header="Size" Width="Auto" />
<materialDesign:DataGridTextColumn Binding="{Binding ArtemisLed.RgbLed.CustomData}" Header="LED data" Width="Auto" />
</DataGrid.Columns>
</DataGrid>
</Grid>
@@ -1,17 +1,92 @@
using Artemis.Core;
using System.Collections.Specialized;
using System.Linq;
using Artemis.Core;
using Stylet;
namespace Artemis.UI.Screens.Settings.Device.Tabs
{
public class DeviceLedsTabViewModel : Screen
{
public DeviceLedsTabViewModel(ArtemisDevice device)
{
Device = device;
DisplayName = "LEDS";
LedViewModels = new BindableCollection<DeviceLedsTabLedViewModel>();
}
public ArtemisDevice Device { get; }
public BindableCollection<DeviceLedsTabLedViewModel> LedViewModels { get; }
private void SelectedLedsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateSelectedLeds();
}
private void UpdateSelectedLeds()
{
foreach (DeviceLedsTabLedViewModel deviceLedsTabLedViewModel in LedViewModels)
deviceLedsTabLedViewModel.Update();
}
#region Overrides of Screen
/// <inheritdoc />
protected override void OnInitialActivate()
{
BindableCollection<ArtemisLed> selectedLeds = ((DeviceDialogViewModel) Parent).SelectedLeds;
LedViewModels.Clear();
LedViewModels.AddRange(Device.Leds.Select(l => new DeviceLedsTabLedViewModel(l, selectedLeds)));
selectedLeds.CollectionChanged += SelectedLedsOnCollectionChanged;
base.OnInitialActivate();
}
/// <inheritdoc />
protected override void OnClose()
{
((DeviceDialogViewModel) Parent).SelectedLeds.CollectionChanged -= SelectedLedsOnCollectionChanged;
base.OnClose();
}
#endregion
}
public class DeviceLedsTabLedViewModel : PropertyChangedBase
{
private readonly BindableCollection<ArtemisLed> _selectedLeds;
private bool _isSelected;
public DeviceLedsTabLedViewModel(ArtemisLed artemisLed, BindableCollection<ArtemisLed> selectedLeds)
{
_selectedLeds = selectedLeds;
ArtemisLed = artemisLed;
Update();
}
public ArtemisLed ArtemisLed { get; }
public bool IsSelected
{
get => _isSelected;
set
{
if (!SetAndNotify(ref _isSelected, value)) return;
Apply();
}
}
public void Update()
{
IsSelected = _selectedLeds.Contains(ArtemisLed);
}
public void Apply()
{
if (IsSelected && !_selectedLeds.Contains(ArtemisLed))
_selectedLeds.Add(ArtemisLed);
else if (!IsSelected && _selectedLeds.Contains(ArtemisLed))
_selectedLeds.Remove(ArtemisLed);
}
}
}