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

Devices - Added keyboard layout selection logic

UI - Improved plugin settings tab performance, added search text highlighting
This commit is contained in:
Robert 2021-03-09 21:33:35 +01:00
parent 46d3a288e9
commit b209bfd833
13 changed files with 308 additions and 88 deletions

View File

@ -287,7 +287,7 @@ namespace Artemis.Core
if (!Enabled || Path == null || LayerShape?.Path == null || !General.PropertiesInitialized || !Transform.PropertiesInitialized) if (!Enabled || Path == null || LayerShape?.Path == null || !General.PropertiesInitialized || !Transform.PropertiesInitialized)
return; return;
// Ensure the brush is ready // Ensure the brush is ready
if (LayerBrush?.BaseProperties?.PropertiesInitialized == false) if (LayerBrush == null || LayerBrush?.BaseProperties?.PropertiesInitialized == false)
return; return;
RenderTimeline(Timeline, canvas); RenderTimeline(Timeline, canvas);

View File

@ -391,12 +391,16 @@ namespace Artemis.Core
if (RgbDevice.DeviceInfo.DeviceType != RGBDeviceType.Keyboard) if (RgbDevice.DeviceInfo.DeviceType != RGBDeviceType.Keyboard)
return; return;
IKeyboard keyboard = (IKeyboard) RgbDevice; IKeyboard? keyboard = RgbDevice as IKeyboard;
// If supported, detect the device layout so that we can load the correct one // If supported, detect the device layout so that we can load the correct one
if (DeviceProvider.CanDetectLogicalLayout) if (DeviceProvider.CanDetectPhysicalLayout && keyboard != null)
LogicalLayout = DeviceProvider.GetLogicalLayout(keyboard);
if (DeviceProvider.CanDetectPhysicalLayout)
PhysicalLayout = (KeyboardLayoutType) keyboard.DeviceInfo.Layout; PhysicalLayout = (KeyboardLayoutType) keyboard.DeviceInfo.Layout;
else
PhysicalLayout = (KeyboardLayoutType) DeviceEntity.PhysicalLayout;
if (DeviceProvider.CanDetectLogicalLayout && keyboard != null)
LogicalLayout = DeviceProvider.GetLogicalLayout(keyboard);
else
LogicalLayout = DeviceEntity.LogicalLayout;
} }
#region Events #region Events

View File

@ -288,12 +288,12 @@ namespace Artemis.UI.Shared
private void DeviceUpdated(object? sender, EventArgs e) private void DeviceUpdated(object? sender, EventArgs e)
{ {
SetupForDevice(); Execute.PostToUIThread(SetupForDevice);
} }
private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e) private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
SetupForDevice(); Execute.PostToUIThread(SetupForDevice);
} }
private void Render() private void Render()

View File

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

View File

@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
namespace Artemis.UI.Behaviors
{
// Source: https://stackoverflow.com/a/60474831/5015269
// Made some changes to add a foreground and background property
public static class HighlightTermBehavior
{
public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
"Text",
typeof(string),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata("", OnTextChanged));
public static readonly DependencyProperty TermToBeHighlightedProperty = DependencyProperty.RegisterAttached(
"TermToBeHighlighted",
typeof(string),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata("", OnTextChanged));
public static readonly DependencyProperty HighlightForegroundProperty = DependencyProperty.RegisterAttached(
"HighlightForeground",
typeof(Color?),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata(null, OnTextChanged));
public static readonly DependencyProperty HighlightBackgroundProperty = DependencyProperty.RegisterAttached(
"HighlightBackground",
typeof(Color?),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata(null, OnTextChanged));
public static string GetText(FrameworkElement frameworkElement)
{
return (string) frameworkElement.GetValue(TextProperty);
}
public static void SetText(FrameworkElement frameworkElement, string value)
{
frameworkElement.SetValue(TextProperty, value);
}
public static string GetTermToBeHighlighted(FrameworkElement frameworkElement)
{
return (string) frameworkElement.GetValue(TermToBeHighlightedProperty);
}
public static void SetTermToBeHighlighted(FrameworkElement frameworkElement, string value)
{
frameworkElement.SetValue(TermToBeHighlightedProperty, value);
}
public static void SetHighlightForeground(FrameworkElement frameworkElement, Color? value)
{
frameworkElement.SetValue(HighlightForegroundProperty, value);
}
public static Color? GetHighlightForeground(FrameworkElement frameworkElement)
{
return (Color?) frameworkElement.GetValue(HighlightForegroundProperty);
}
public static void SetHighlightBackground(FrameworkElement frameworkElement, Color? value)
{
frameworkElement.SetValue(HighlightBackgroundProperty, value);
}
public static Color? GetHighlightBackground(FrameworkElement frameworkElement)
{
return (Color?) frameworkElement.GetValue(HighlightBackgroundProperty);
}
public static List<string> SplitTextIntoTermAndNotTermParts(string text, string term)
{
if (string.IsNullOrEmpty(text))
return new List<string> {string.Empty};
return Regex.Split(text, $@"({Regex.Escape(term)})", RegexOptions.IgnoreCase)
.Where(p => p != string.Empty)
.ToList();
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBlock textBlock)
SetTextBlockTextAndHighlightTerm(textBlock, GetText(textBlock), GetTermToBeHighlighted(textBlock));
}
private static void SetTextBlockTextAndHighlightTerm(TextBlock textBlock, string text, string termToBeHighlighted)
{
textBlock.Text = string.Empty;
if (TextIsEmpty(text))
return;
if (TextIsNotContainingTermToBeHighlighted(text, termToBeHighlighted))
{
AddPartToTextBlock(textBlock, text);
return;
}
List<string> textParts = SplitTextIntoTermAndNotTermParts(text, termToBeHighlighted);
foreach (string textPart in textParts)
AddPartToTextBlockAndHighlightIfNecessary(textBlock, termToBeHighlighted, textPart);
}
private static bool TextIsEmpty(string text)
{
return text.Length == 0;
}
private static bool TextIsNotContainingTermToBeHighlighted(string text, string termToBeHighlighted)
{
if (text == null || termToBeHighlighted == null)
return true;
return text.Contains(termToBeHighlighted, StringComparison.OrdinalIgnoreCase) == false;
}
private static void AddPartToTextBlockAndHighlightIfNecessary(TextBlock textBlock, string termToBeHighlighted, string textPart)
{
if (textPart.Equals(termToBeHighlighted, StringComparison.OrdinalIgnoreCase))
AddHighlightedPartToTextBlock(textBlock, textPart);
else
AddPartToTextBlock(textBlock, textPart);
}
private static void AddPartToTextBlock(TextBlock textBlock, string part)
{
textBlock.Inlines.Add(new Run {Text = part});
}
private static void AddHighlightedPartToTextBlock(TextBlock textBlock, string part)
{
Color? foreground = GetHighlightForeground(textBlock);
Color? background = GetHighlightBackground(textBlock);
if (background == null)
{
Run run = new() {Text = part, FontWeight = FontWeights.ExtraBold};
if (foreground != null)
run.Foreground = new SolidColorBrush(foreground.Value);
textBlock.Inlines.Add(run);
return;
}
Border border = new()
{
Background = new SolidColorBrush(background.Value),
BorderThickness = new Thickness(0),
CornerRadius = new CornerRadius(2),
Child = new TextBlock {Text = part, FontWeight = FontWeights.Bold},
Padding = new Thickness(1),
Margin = new Thickness(-1, -5, -1, -5)
};
if (foreground != null)
((TextBlock) border.Child).Foreground = new SolidColorBrush(foreground.Value);
textBlock.Inlines.Add(border);
}
}
}

View File

@ -90,6 +90,9 @@ namespace Artemis.UI
IRegistrationService registrationService = Kernel.Get<IRegistrationService>(); IRegistrationService registrationService = Kernel.Get<IRegistrationService>();
registrationService.RegisterInputProvider(); registrationService.RegisterInputProvider();
registrationService.RegisterControllers(); registrationService.RegisterControllers();
// Initialize background services
Kernel.Get<IDeviceLayoutService>();
} }
protected override void ConfigureIoC(IKernel kernel) protected override void ConfigureIoC(IKernel kernel)

View File

@ -24,12 +24,11 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
_settingsVmFactory = settingsVmFactory; _settingsVmFactory = settingsVmFactory;
} }
protected override void OnActivate() protected override void OnInitialActivate()
{ {
// Take it off the UI thread to avoid freezing on tab change // Take it off the UI thread to avoid freezing on tab change
Task.Run(async () => Task.Run(async () =>
{ {
Items.Clear();
await Task.Delay(200); await Task.Delay(200);
List<DeviceSettingsViewModel> instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList(); List<DeviceSettingsViewModel> instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
@ -37,7 +36,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
Items.Add(deviceSettingsViewModel); Items.Add(deviceSettingsViewModel);
}); });
base.OnActivate(); base.OnInitialActivate();
} }
public async Task<bool> ShowDeviceDisableDialog() public async Task<bool> ShowDeviceDisableDialog()

View File

@ -27,13 +27,13 @@
Width="20" Width="20"
VerticalAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Visibility="{Binding LoadException, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" /> Visibility="{Binding LoadException, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted, FallbackValue=Collapsed}" />
<Button Grid.Column="0" <Button Grid.Column="0"
Margin="-8" Margin="-8"
VerticalAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Visibility="{Binding LoadException, Converter={StaticResource NullToVisibilityConverter}}" Visibility="{Binding LoadException, Converter={StaticResource NullToVisibilityConverter}, FallbackValue=Collapsed}"
Style="{StaticResource MaterialDesignIconButton}" Style="{StaticResource MaterialDesignIconButton}"
Foreground="#E74C4C" Foreground="#E74C4C"
ToolTip="An exception occurred while enabling this feature, click to view" ToolTip="An exception occurred while enabling this feature, click to view"
@ -46,13 +46,13 @@
<!-- Enable toggle column --> <!-- Enable toggle column -->
<StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="8" <StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="8"
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}"> Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay, FallbackValue=Collapsed}">
<CheckBox Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding IsEnabled}"> <CheckBox Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding IsEnabled}">
Feature enabled Feature enabled
</CheckBox> </CheckBox>
</StackPanel> </StackPanel>
<StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="7" <StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="7"
Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"> Visibility="{Binding Enabling, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay, FallbackValue=Collapsed}">
<ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" Value="0" IsIndeterminate="True" /> <ProgressBar Style="{StaticResource MaterialDesignCircularProgressBar}" Value="0" IsIndeterminate="True" />
</StackPanel> </StackPanel>

View File

@ -65,18 +65,20 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
protected override void OnInitialActivate() protected override void OnInitialActivate()
{ {
base.OnInitialActivate();
_pluginManagementService.PluginFeatureEnabling += OnFeatureEnabling; _pluginManagementService.PluginFeatureEnabling += OnFeatureEnabling;
_pluginManagementService.PluginFeatureEnabled += OnFeatureEnableStopped; _pluginManagementService.PluginFeatureEnabled += OnFeatureEnableStopped;
_pluginManagementService.PluginFeatureEnableFailed += OnFeatureEnableStopped; _pluginManagementService.PluginFeatureEnableFailed += OnFeatureEnableStopped;
base.OnInitialActivate();
} }
protected override void OnClose() protected override void OnClose()
{ {
base.OnClose();
_pluginManagementService.PluginFeatureEnabling -= OnFeatureEnabling; _pluginManagementService.PluginFeatureEnabling -= OnFeatureEnabling;
_pluginManagementService.PluginFeatureEnabled -= OnFeatureEnableStopped; _pluginManagementService.PluginFeatureEnabled -= OnFeatureEnableStopped;
_pluginManagementService.PluginFeatureEnableFailed -= OnFeatureEnableStopped; _pluginManagementService.PluginFeatureEnableFailed -= OnFeatureEnableStopped;
base.OnClose();
} }
private async Task UpdateEnabled(bool enable) private async Task UpdateEnabled(bool enable)

View File

@ -14,7 +14,7 @@
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid Margin="0 15" MinWidth="810" Width="{Binding Path=ActualWidth, ElementName=PluginsContainer}"> <Grid Margin="0 15" Width="810">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
@ -41,21 +41,36 @@
IMPORT PLUGIN IMPORT PLUGIN
</Button> </Button>
</Grid> </Grid>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<ItemsControl ItemsSource="{Binding Items}" Margin="15 0 15 15" HorizontalAlignment="Center" MaxWidth="1700" x:Name="PluginsContainer">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding IsAsync=True}" Margin="5" HorizontalAlignment="Left" VerticalAlignment="Top" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer> <ListBox Grid.Row="1"
ItemsSource="{Binding Items}"
materialDesign:RippleAssist.IsDisabled="True"
VirtualizingPanel.ScrollUnit="Pixel"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center"
Margin="15 0 15 15">
<ListBox.ItemTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding IsAsync=True}" Margin="5" HorizontalAlignment="Center" IsTabStop="False" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid> </Grid>
</UserControl> </UserControl>

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Extensions;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using Ookii.Dialogs.Wpf; using Ookii.Dialogs.Wpf;
@ -43,26 +44,36 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
if (_instances == null) if (_instances == null)
return; return;
Items.Clear(); List<PluginSettingsViewModel> instances = _instances;
string search = SearchPluginInput?.ToLower();
if (!string.IsNullOrWhiteSpace(search))
instances = instances.Where(i => i.Plugin.Info.Name.ToLower().Contains(search) ||
i.Plugin.Info.Description != null && i.Plugin.Info.Description.ToLower().Contains(search)).ToList();
if (string.IsNullOrWhiteSpace(SearchPluginInput)) foreach (PluginSettingsViewModel pluginSettingsViewModel in instances)
Items.AddRange(_instances); {
else if (!Items.Contains(pluginSettingsViewModel))
Items.AddRange(_instances.Where(i => i.Plugin.Info.Name.Contains(SearchPluginInput, StringComparison.OrdinalIgnoreCase) || Items.Add(pluginSettingsViewModel);
i.Plugin.Info.Description.Contains(SearchPluginInput, StringComparison.OrdinalIgnoreCase))); }
foreach (PluginSettingsViewModel pluginSettingsViewModel in Items.ToList())
{
if (!instances.Contains(pluginSettingsViewModel))
Items.Remove(pluginSettingsViewModel);
}
((BindableCollection<PluginSettingsViewModel>) Items).Sort(i => i.Plugin.Info.Name);
} }
protected override void OnActivate() protected override void OnInitialActivate()
{ {
// Take it off the UI thread to avoid freezing on tab change // Take it off the UI thread to avoid freezing on tab change
Task.Run(async () => Task.Run(async () =>
{ {
Items.Clear();
await Task.Delay(200); await Task.Delay(200);
GetPluginInstances(); GetPluginInstances();
}); });
base.OnActivate(); base.OnInitialActivate();
} }
public void ImportPlugin() public void ImportPlugin()

View File

@ -8,6 +8,7 @@
xmlns:devices="clr-namespace:Artemis.UI.Screens.Settings.Tabs.Plugins" xmlns:devices="clr-namespace:Artemis.UI.Screens.Settings.Tabs.Plugins"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors" xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared"
xmlns:behaviors="clr-namespace:Artemis.UI.Behaviors"
d:DataContext="{d:DesignInstance devices:PluginSettingsViewModel}" d:DataContext="{d:DesignInstance devices:PluginSettingsViewModel}"
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"> d:DesignHeight="450" d:DesignWidth="800">
@ -34,20 +35,27 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<shared:ArtemisIcon Icon="{Binding Icon}" <shared:ArtemisIcon Icon="{Binding Icon}"
Width="48" Width="48"
Height="48" Height="48"
Margin="0 5 0 0" Margin="0 5 0 0"
Grid.Row="0" Grid.Row="0"
Grid.RowSpan="2" Grid.RowSpan="2"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Top" /> VerticalAlignment="Top" />
<TextBlock Grid.Column="1" Grid.Row="0" Style="{StaticResource MaterialDesignBody2TextBlock}" Text="{Binding Plugin.Info.Name}" /> <TextBlock Grid.Column="1" Grid.Row="0" Style="{StaticResource MaterialDesignBody2TextBlock}"
behaviors:HighlightTermBehavior.TermToBeHighlighted="{Binding Parent.SearchPluginInput}"
behaviors:HighlightTermBehavior.Text="{Binding Plugin.Info.Name}"
behaviors:HighlightTermBehavior.HighlightForeground="{StaticResource Primary600Foreground}"
behaviors:HighlightTermBehavior.HighlightBackground="{StaticResource Primary600}"/>
<TextBlock Grid.Column="1" <TextBlock Grid.Column="1"
Grid.Row="1" Grid.Row="1"
TextWrapping="Wrap" TextWrapping="Wrap"
Text="{Binding Plugin.Info.Description}" behaviors:HighlightTermBehavior.TermToBeHighlighted="{Binding Parent.SearchPluginInput}"
behaviors:HighlightTermBehavior.Text="{Binding Plugin.Info.Description}"
behaviors:HighlightTermBehavior.HighlightForeground="{StaticResource Primary600Foreground}"
behaviors:HighlightTermBehavior.HighlightBackground="{StaticResource Primary600}"
Style="{StaticResource MaterialDesignTextBlock}" Style="{StaticResource MaterialDesignTextBlock}"
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" /> Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" />
</Grid> </Grid>
@ -88,7 +96,7 @@
<materialDesign:PackIcon Kind="ShieldHalfFull" <materialDesign:PackIcon Kind="ShieldHalfFull"
Margin="5 0 0 0" Margin="5 0 0 0"
ToolTip="Plugin requires admin rights" ToolTip="Plugin requires admin rights"
Visibility="{Binding Plugin.Info.RequiresAdmin, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"/> Visibility="{Binding Plugin.Info.RequiresAdmin, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
</StackPanel> </StackPanel>
</CheckBox> </CheckBox>
@ -128,7 +136,7 @@
</b:Interaction.Behaviors> </b:Interaction.Behaviors>
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" /> <ContentControl s:View.Model="{Binding IsAsync=True}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
</DataTemplate> </DataTemplate>
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
</ListBox> </ListBox>

View File

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
@ -9,7 +8,6 @@ using Artemis.UI.Screens.Settings.Device;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using MaterialDesignThemes.Wpf; using MaterialDesignThemes.Wpf;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Layout;
using KeyboardLayoutType = Artemis.Core.KeyboardLayoutType; using KeyboardLayoutType = Artemis.Core.KeyboardLayoutType;
namespace Artemis.UI.Services namespace Artemis.UI.Services
@ -17,10 +15,10 @@ namespace Artemis.UI.Services
public class DeviceLayoutService : IDeviceLayoutService public class DeviceLayoutService : IDeviceLayoutService
{ {
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly List<ArtemisDevice> _ignoredDevices;
private readonly IMessageService _messageService;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly IWindowService _windowService; private readonly IWindowService _windowService;
private readonly IMessageService _messageService;
private readonly List<ArtemisDevice> _ignoredDevices;
public DeviceLayoutService(IDialogService dialogService, IRgbService rgbService, IWindowService windowService, IMessageService messageService) public DeviceLayoutService(IDialogService dialogService, IRgbService rgbService, IWindowService windowService, IMessageService messageService)
{ {
@ -31,34 +29,46 @@ namespace Artemis.UI.Services
_ignoredDevices = new List<ArtemisDevice>(); _ignoredDevices = new List<ArtemisDevice>();
rgbService.DeviceAdded += RgbServiceOnDeviceAdded; rgbService.DeviceAdded += RgbServiceOnDeviceAdded;
windowService.MainWindowOpened += async (_, _) => await RequestLayoutInput(); windowService.MainWindowOpened += WindowServiceOnMainWindowOpened;
} }
private async Task RequestLayoutInput() private async Task RequestLayoutInput(ArtemisDevice artemisDevice)
{
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);
return;
}
await _dialogService.ShowDialog<DeviceLayoutDialogViewModel>(new Dictionary<string, object> {{"device", artemisDevice}});
}
private bool DeviceNeedsLayout(ArtemisDevice d)
{
return d.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard &&
(d.LogicalLayout == null || d.PhysicalLayout == KeyboardLayoutType.Unknown) &&
(!d.DeviceProvider.CanDetectLogicalLayout || !d.DeviceProvider.CanDetectPhysicalLayout);
}
#region Event handlers
private async void WindowServiceOnMainWindowOpened(object? sender, EventArgs e)
{ {
List<ArtemisDevice> devices = _rgbService.Devices.Where(device => DeviceNeedsLayout(device) && !_ignoredDevices.Contains(device)).ToList(); List<ArtemisDevice> devices = _rgbService.Devices.Where(device => DeviceNeedsLayout(device) && !_ignoredDevices.Contains(device)).ToList();
foreach (ArtemisDevice artemisDevice in devices) foreach (ArtemisDevice artemisDevice in devices)
{ await RequestLayoutInput(artemisDevice);
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) private async void RgbServiceOnDeviceAdded(object sender, DeviceEventArgs e)
{ {
if (!DeviceNeedsLayout(e.Device)) if (_ignoredDevices.Contains(e.Device) || !DeviceNeedsLayout(e.Device))
return; return;
if (!_windowService.IsMainWindowOpen) if (!_windowService.IsMainWindowOpen)
@ -66,12 +76,11 @@ namespace Artemis.UI.Services
_messageService.ShowNotification("New device detected", "Detected a new device that needs layout setup", PackIconKind.Keyboard); _messageService.ShowNotification("New device detected", "Detected a new device that needs layout setup", PackIconKind.Keyboard);
return; return;
} }
await RequestLayoutInput(e.Device);
} }
private bool DeviceNeedsLayout(ArtemisDevice d) => d.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Keyboard && #endregion
d.LogicalLayout == null ||
d.PhysicalLayout == KeyboardLayoutType.Unknown &&
(!d.DeviceProvider.CanDetectLogicalLayout || !d.DeviceProvider.CanDetectPhysicalLayout);
} }
public interface IDeviceLayoutService : IArtemisUIService public interface IDeviceLayoutService : IArtemisUIService