1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

UI - Added keyboard layout selection UI

This commit is contained in:
Robert 2021-03-09 00:30:11 +01:00
parent ea1633c322
commit 46d3a288e9
20 changed files with 460 additions and 12 deletions

View File

@ -306,7 +306,7 @@ namespace Artemis.Core
{
// Take out invalid file name chars, may not be perfect but neither are you
string fileName = System.IO.Path.GetInvalidFileNameChars().Aggregate(RgbDevice.DeviceInfo.Model, (current, c) => current.Replace(c, '-'));
if (RgbDevice is IKeyboard)
if (RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard)
fileName = $"{fileName}-{PhysicalLayout.ToString().ToUpper()}";
if (includeExtension)
fileName = $"{fileName}.xml";
@ -388,9 +388,10 @@ namespace Artemis.Core
private void ApplyKeyboardLayout()
{
if (!(RgbDevice is IKeyboard keyboard))
if (RgbDevice.DeviceInfo.DeviceType != RGBDeviceType.Keyboard)
return;
IKeyboard keyboard = (IKeyboard) RgbDevice;
// If supported, detect the device layout so that we can load the correct one
if (DeviceProvider.CanDetectLogicalLayout)
LogicalLayout = DeviceProvider.GetLogicalLayout(keyboard);

View File

@ -1,4 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using RGB.NET.Core;

View File

@ -12,9 +12,12 @@ namespace Artemis.UI.Shared
{
internal class DeviceVisualizerLed
{
private const byte Dimmed = 100;
private const byte NonDimmed = 255;
private SolidColorBrush? _renderColorBrush;
private Color _renderColor;
public DeviceVisualizerLed(ArtemisLed led)
{
Led = led;
@ -49,6 +52,7 @@ namespace Artemis.UI.Shared
byte b = Led.RgbLed.Color.GetB();
_renderColor.A = (byte)(isDimmed ? 100 : 255);
_renderColor.A = isDimmed ? Dimmed : NonDimmed;
_renderColor.R = r;
_renderColor.G = g;
_renderColor.B = b;

View File

@ -17,7 +17,7 @@
Text="{Binding Text}"
TextWrapping="Wrap" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 8 0 0">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="16">
<Button Style="{StaticResource MaterialDesignFlatButton}"
Focusable="False"
IsCancel="True"

View File

@ -126,6 +126,11 @@
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate.cur" />
<Resource Include="Resources\Images\PhysicalLayouts\abnt.png" />
<Resource Include="Resources\Images\PhysicalLayouts\ansi.png" />
<Resource Include="Resources\Images\PhysicalLayouts\iso.png" />
<Resource Include="Resources\Images\PhysicalLayouts\jis.png" />
<Resource Include="Resources\Images\PhysicalLayouts\ks.png" />
<Resource Include="Resources\Images\Sidebar\sidebar-header.png" />
</ItemGroup>
<ItemGroup>
@ -306,6 +311,11 @@
<None Remove="Resources\Fonts\RobotoMono-Regular.ttf" />
<None Remove="Resources\Images\Logo\bow.svg" />
<None Remove="Resources\Images\Logo\logo-512.ico" />
<None Remove="Resources\Images\PhysicalLayouts\abnt.png" />
<None Remove="Resources\Images\PhysicalLayouts\ansi.png" />
<None Remove="Resources\Images\PhysicalLayouts\iso.png" />
<None Remove="Resources\Images\PhysicalLayouts\jis.png" />
<None Remove="Resources\Images\PhysicalLayouts\ks.png" />
<None Remove="Resources\Images\Sidebar\sidebar-header.png" />
</ItemGroup>
<ItemGroup>

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -27,10 +27,12 @@
<TextBlock Grid.Column="0">
This image shows what is being rendered and dispatched to RGB.NET
</TextBlock>
<TextBlock Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,5,0" FontWeight="Bold">
FPS:
<TextBlock Grid.Column="1" HorizontalAlignment="Right" Margin="0,0,5,0">
<Run Text="FPS: "></Run>
<Run FontWeight="Bold" Text="{Binding CurrentFps}"></Run>
<Run Text=" at "></Run>
<Run Text="{Binding RenderWidth}"/><Run Text="x"></Run><Run Text="{Binding RenderHeight}"/>
</TextBlock>
<TextBlock Grid.Column="2" HorizontalAlignment="Right" Text="{Binding CurrentFps}" />
</Grid>
<materialDesign:Card Grid.Row="2" Margin="0,5,0,0" Background="{StaticResource Checkerboard}">

View File

@ -15,6 +15,8 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
private readonly ICoreService _coreService;
private double _currentFps;
private ImageSource _currentFrame;
private int _renderWidth;
private int _renderHeight;
public RenderDebugViewModel(ICoreService coreService)
{
@ -34,6 +36,18 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
set => SetAndNotify(ref _currentFps, value);
}
public int RenderWidth
{
get => _renderWidth;
set => SetAndNotify(ref _renderWidth, value);
}
public int RenderHeight
{
get => _renderHeight;
set => SetAndNotify(ref _renderHeight, value);
}
protected override void OnActivate()
{
_coreService.FrameRendered += CoreServiceOnFrameRendered;
@ -56,6 +70,8 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
return;
SKImageInfo bitmapInfo = e.Texture.Bitmap.Info;
RenderHeight = bitmapInfo.Height;
RenderWidth = bitmapInfo.Width;
if (!(CurrentFrame is WriteableBitmap writeableBitmap) ||
writeableBitmap.Width != bitmapInfo.Width ||

View File

@ -0,0 +1,187 @@
<UserControl x:Class="Artemis.UI.Screens.Settings.Device.DeviceLayoutDialogView"
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:local="clr-namespace:Artemis.UI.Screens.Settings.Device"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mde="https://spiegelp.github.io/MaterialDesignExtensions/winfx/xaml"
mc:Ignorable="d"
d:DesignHeight="1200" d:DesignWidth="1200"
d:DataContext="{d:DesignInstance local:DeviceLayoutDialogViewModel}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="16" Width="1200" Height="800" Visibility="{Binding SelectPhysicalLayout, Converter={x:Static s:BoolToVisibilityConverter.Instance}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" TextWrapping="Wrap" Margin="0 0 0 20">
Select a physical layout
</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
Foreground="{DynamicResource MaterialDesignBodyLight}"
TextWrapping="Wrap">
Artemis couldn't automatically determine the physical layout of your <Run Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName, Mode=OneWay}" />. <LineBreak />
In order for Artemis to know which keys are on your keyboard and where they're located, select the matching layout below.
<LineBreak />
<LineBreak />
P.S. Don't worry about missing special keys like num keys/function keys or macro keys, they aren't important here.
</TextBlock>
</StackPanel>
<ScrollViewer Grid.Row="1" Margin="0 25">
<WrapPanel HorizontalAlignment="Center">
<Button Style="{StaticResource MaterialDesignFlatButton}"
Foreground="{DynamicResource MaterialDesignBody}"
Command="{s:Action ApplyPhysicalLayout}"
CommandParameter="ISO"
HorizontalAlignment="Right"
Margin="0 0 10 0"
Width="550"
Height="280">
<StackPanel>
<Image Source="/Resources/Images/PhysicalLayouts/iso.png" />
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignHeadline6TextBlock}" Margin="0 10 0 0">
ISO
</TextBlock>
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignBody2TextBlock}" TextWrapping="Wrap">
Most commonly used in the EU (tall enter)
</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}"
Foreground="{DynamicResource MaterialDesignBody}"
Command="{s:Action ApplyPhysicalLayout}"
CommandParameter="ANSI"
HorizontalAlignment="Right"
Margin="0 0 10 0"
Width="550"
Height="280">
<StackPanel>
<Image Source="/Resources/Images/PhysicalLayouts/ansi.png" />
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignHeadline6TextBlock}" Margin="0 10 0 0">
ANSI
</TextBlock>
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignBody2TextBlock}" TextWrapping="Wrap">
Most commonly used in the US (short enter)
</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}"
Foreground="{DynamicResource MaterialDesignBody}"
Command="{s:Action ApplyPhysicalLayout}"
CommandParameter="ABNT"
HorizontalAlignment="Right"
Margin="0 0 10 0"
Width="550"
Height="280">
<StackPanel>
<Image Source="/Resources/Images/PhysicalLayouts/abnt.png" />
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignHeadline6TextBlock}" Margin="0 10 0 0">
ABNT
</TextBlock>
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignBody2TextBlock}" TextWrapping="Wrap">
Most commonly used in Brazil/Portugal (based on ISO)
</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}"
Foreground="{DynamicResource MaterialDesignBody}"
Command="{s:Action ApplyPhysicalLayout}"
CommandParameter="KS"
HorizontalAlignment="Right"
Margin="0 0 10 0"
Width="550"
Height="280">
<StackPanel>
<Image Source="/Resources/Images/PhysicalLayouts/ks.png" />
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignHeadline6TextBlock}" Margin="0 10 0 0">
KS
</TextBlock>
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignBody2TextBlock}" TextWrapping="Wrap">
Most commonly used in South Korea
</TextBlock>
</StackPanel>
</Button>
<Button Style="{StaticResource MaterialDesignFlatButton}"
Foreground="{DynamicResource MaterialDesignBody}"
Command="{s:Action ApplyPhysicalLayout}"
CommandParameter="JIS"
HorizontalAlignment="Right"
Margin="0 0 10 0"
Width="550"
Height="280">
<StackPanel>
<Image Source="/Resources/Images/PhysicalLayouts/jis.png" />
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignHeadline6TextBlock}" Margin="0 10 0 0">
JIS
</TextBlock>
<TextBlock TextAlignment="Center" Style="{StaticResource MaterialDesignBody2TextBlock}" TextWrapping="Wrap">
Most commonly used in Japan (based on ISO)
</TextBlock>
</StackPanel>
</Button>
</WrapPanel>
</ScrollViewer>
</Grid>
<StackPanel Grid.Row="0" Margin="16" Width="800" Visibility="{Binding SelectPhysicalLayout, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}}">
<StackPanel>
<TextBlock Style="{StaticResource MaterialDesignHeadline6TextBlock}" TextWrapping="Wrap" Margin="0 0 0 20">
Select a logical layout
</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
Foreground="{DynamicResource MaterialDesignBodyLight}"
TextWrapping="Wrap">
Artemis couldn't automatically determine the logical layout of your <Run Text="{Binding Device.RgbDevice.DeviceInfo.DeviceName, Mode=OneWay}" />. <LineBreak /><LineBreak />
While not as important as the physical layout, setting the correct logical layout will allow Artemis to show the right keycaps (if a matching layout file is present)
</TextBlock>
</StackPanel>
<mde:Autocomplete Style="{StaticResource MaterialDesignAutocomplete}"
AutocompleteSource="{Binding Path=AutocompleteSource}"
SearchOnInitialFocus="True"
SelectedItem="{Binding SelectedRegion, Mode=TwoWay}"
Hint="Select a logical layout"
Margin="0,16,0,0"
FontSize="15"
Foreground="{DynamicResource MaterialDesignBody}"
Background="{DynamicResource MaterialDesignPaper}">
<mde:Autocomplete.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="14" VerticalAlignment="Center">
<Run Text="{Binding EnglishName, Mode=OneWay}" />
(<Run FontWeight="SemiBold" Text="{Binding TwoLetterISORegionName, Mode=OneWay}" />)
</TextBlock>
</DataTemplate>
</mde:Autocomplete.ItemTemplate>
</mde:Autocomplete>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right" Margin="16">
<Button Style="{StaticResource MaterialDesignFlatButton}"
Focusable="False"
IsCancel="True"
Command="{s:Action Cancel}"
Content="CANCEL" />
<Button x:Name="ConfirmButton"
Style="{StaticResource MaterialDesignFlatButton}"
IsDefault="True"
Focusable="True"
Command="{s:Action Confirm}"
Content="CONFIRM" />
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,125 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared.Services;
using MaterialDesignExtensions.Model;
namespace Artemis.UI.Screens.Settings.Device
{
public class DeviceLayoutDialogViewModel : DialogViewModelBase
{
private readonly IRgbService _rgbService;
private bool _selectPhysicalLayout;
private RegionInfoAutocompleteSource _autocompleteSource;
private RegionInfo _selectedRegion;
public DeviceLayoutDialogViewModel(ArtemisDevice device, IRgbService rgbService)
{
_rgbService = rgbService;
Device = device;
SelectPhysicalLayout = !device.DeviceProvider.CanDetectPhysicalLayout;
Task.Run(() =>
{
AutocompleteSource = new RegionInfoAutocompleteSource();
SelectedRegion = AutocompleteSource.Regions.FirstOrDefault(r => r.TwoLetterISORegionName == Device.LogicalLayout ||
r.TwoLetterISORegionName == "US" && Device.LogicalLayout == "NA");
});
}
public ArtemisDevice Device { get; }
public RegionInfoAutocompleteSource AutocompleteSource
{
get => _autocompleteSource;
set => SetAndNotify(ref _autocompleteSource, value);
}
public RegionInfo SelectedRegion
{
get => _selectedRegion;
set
{
SetAndNotify(ref _selectedRegion, value);
NotifyOfPropertyChange(nameof(CanConfirm));
}
}
public bool SelectPhysicalLayout
{
get => _selectPhysicalLayout;
set => SetAndNotify(ref _selectPhysicalLayout, value);
}
public bool CanConfirm => SelectedRegion != null;
public void ApplyPhysicalLayout(string physicalLayout)
{
Device.PhysicalLayout = Enum.Parse<KeyboardLayoutType>(physicalLayout);
_rgbService.SaveDevice(Device);
_rgbService.ApplyBestDeviceLayout(Device);
SelectPhysicalLayout = false;
}
private void ApplyLogicalLayout(string logicalLayout)
{
Device.LogicalLayout = logicalLayout;
_rgbService.SaveDevice(Device);
_rgbService.ApplyBestDeviceLayout(Device);
}
public void Confirm()
{
if (!CanConfirm || Session == null || Session.IsEnded)
return;
ApplyLogicalLayout(SelectedRegion.TwoLetterISORegionName);
Session?.Close(true);
}
}
public class RegionInfoAutocompleteSource : IAutocompleteSource<RegionInfo>
{
public List<RegionInfo> Regions { get; set; }
public RegionInfoAutocompleteSource()
{
Regions = CultureInfo.GetCultures(CultureTypes.SpecificCultures).ToList()
.Select(c => new RegionInfo(c.LCID))
.GroupBy(r => r.EnglishName)
.Select(g => g.First())
.OrderBy(r => r.EnglishName)
.ToList();
}
IEnumerable<RegionInfo> IAutocompleteSource<RegionInfo>.Search(string searchTerm)
{
if (searchTerm == null)
return Regions;
searchTerm = searchTerm.ToLower();
return Regions.Where(r => r.EnglishName.ToLower().Contains(searchTerm) ||
r.NativeName.ToLower().Contains(searchTerm) ||
r.TwoLetterISORegionName.ToLower().Contains(searchTerm));
}
public IEnumerable Search(string searchTerm)
{
if (searchTerm == null)
return Regions;
searchTerm = searchTerm.ToLower();
return Regions.Where(r => r.EnglishName.ToLower().Contains(searchTerm) ||
r.NativeName.ToLower().Contains(searchTerm) ||
r.TwoLetterISORegionName.ToLower().Contains(searchTerm));
}
}
}

View File

@ -12,7 +12,7 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
DisplayName = "INFO";
}
public bool IsKeyboard => Device.RgbDevice is IKeyboard;
public bool IsKeyboard => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard;
public ArtemisDevice Device { get; }
}
}

View File

@ -174,6 +174,10 @@
</StackPanel>
</materialDesign:HintAssist.Hint>
</TextBox>
<Button Style="{StaticResource MaterialDesignRaisedButton}" Margin="0 8 8 0" Command="{s:Action SelectPhysicalLayout}">
SELECT PHYSICAL LAYOUT (PLACEHOLDER)
</Button>
</StackPanel>
<!-- Buttons -->

View File

@ -1,4 +1,5 @@
using System.ComponentModel;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
@ -15,6 +16,7 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
{
private readonly ICoreService _coreService;
private readonly IMessageService _messageService;
private readonly IDialogService _dialogService;
private readonly IRgbService _rgbService;
private float _blueScale;
private SKColor _currentColor;
@ -33,11 +35,13 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
ICoreService coreService,
IRgbService rgbService,
IMessageService messageService,
IDialogService dialogService,
IModelValidator<DevicePropertiesTabViewModel> validator) : base(validator)
{
_coreService = coreService;
_rgbService = rgbService;
_messageService = messageService;
_dialogService = dialogService;
Device = device;
DisplayName = "PROPERTIES";
@ -126,6 +130,11 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
}
}
public async Task SelectPhysicalLayout()
{
await _dialogService.ShowDialog<DeviceLayoutDialogViewModel>(new Dictionary<string, object> {{"device", Device}});
}
public async Task Apply()
{
await ValidateAsync();
@ -167,12 +176,21 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
_initialGreenScale = Device.GreenScale;
_initialBlueScale = Device.BlueScale;
CurrentColor = SKColors.White;
_coreService.FrameRendering += OnFrameRendering;
Device.PropertyChanged += DeviceOnPropertyChanged;
base.OnActivate();
}
protected override void OnDeactivate()
{
_coreService.FrameRendering -= OnFrameRendering;
Device.PropertyChanged -= DeviceOnPropertyChanged;
base.OnDeactivate();
}
#region Event handlers
private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e)

View File

@ -84,7 +84,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
public void ViewProperties()
{
_windowManager.ShowDialog(_deviceDebugVmFactory.DeviceDialogViewModel(Device));
_windowManager.ShowWindow(_deviceDebugVmFactory.DeviceDialogViewModel(Device));
}
private async Task UpdateIsDeviceEnabled(bool value)
{

View File

@ -241,7 +241,7 @@ namespace Artemis.UI.Screens.SurfaceEditor
public void ViewProperties(ArtemisDevice device)
{
_windowManager.ShowDialog(_deviceDebugVmFactory.DeviceDialogViewModel(device));
_windowManager.ShowWindow(_deviceDebugVmFactory.DeviceDialogViewModel(device));
}
public async Task DetectInput(ArtemisDevice device)

View File

@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.Settings.Device;
using Artemis.UI.Shared.Services;
using MaterialDesignThemes.Wpf;
using RGB.NET.Core;
using RGB.NET.Layout;
using KeyboardLayoutType = Artemis.Core.KeyboardLayoutType;
namespace Artemis.UI.Services
{
public class DeviceLayoutService : IDeviceLayoutService
{
private readonly IDialogService _dialogService;
private readonly IRgbService _rgbService;
private readonly IWindowService _windowService;
private readonly IMessageService _messageService;
private readonly List<ArtemisDevice> _ignoredDevices;
public DeviceLayoutService(IDialogService dialogService, IRgbService rgbService, IWindowService windowService, IMessageService messageService)
{
_dialogService = dialogService;
_rgbService = rgbService;
_windowService = windowService;
_messageService = messageService;
_ignoredDevices = new List<ArtemisDevice>();
rgbService.DeviceAdded += RgbServiceOnDeviceAdded;
windowService.MainWindowOpened += async (_, _) => await RequestLayoutInput();
}
private async Task RequestLayoutInput()
{
List<ArtemisDevice> devices = _rgbService.Devices.Where(device => DeviceNeedsLayout(device) && !_ignoredDevices.Contains(device)).ToList();
foreach (ArtemisDevice artemisDevice in devices)
{
bool configure = await _dialogService.ShowConfirmDialog(
"Device requires layout info",
$"Artemis could not detect the layout of your {artemisDevice.RgbDevice.DeviceInfo.DeviceName}. Please configure out manually",
"Configure",
"Ignore for now"
);
if (!configure)
{
_ignoredDevices.Add(artemisDevice);
continue;
}
await _dialogService.ShowDialog<DeviceLayoutDialogViewModel>(new Dictionary<string, object> {{"device", artemisDevice}});
}
}
private void RgbServiceOnDeviceAdded(object sender, DeviceEventArgs e)
{
if (!DeviceNeedsLayout(e.Device))
return;
if (!_windowService.IsMainWindowOpen)
{
_messageService.ShowNotification("New device detected", "Detected a new device that needs layout setup", PackIconKind.Keyboard);
return;
}
}
private bool DeviceNeedsLayout(ArtemisDevice d) => d.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard &&
d.LogicalLayout == null ||
d.PhysicalLayout == KeyboardLayoutType.Unknown &&
(!d.DeviceProvider.CanDetectLogicalLayout || !d.DeviceProvider.CanDetectPhysicalLayout);
}
public interface IDeviceLayoutService : IArtemisUIService
{
}
}