Code style - Use file scoped namespaces

Code style - Ran code cleanup
This commit is contained in:
Robert committed 2022-08-21 11:36:15 +02:00
1 parent e68e16df4d
commit f6090dc296
691 files changed
+37301 -38119

No files matched your search

@@ -1,18 +1,17 @@
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device
{
public class DeviceDetectInputView : ReactiveUserControl<DeviceDetectInputViewModel>
{
public DeviceDetectInputView()
{
InitializeComponent();
}
namespace Artemis.UI.Screens.Device;
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public class DeviceDetectInputView : ReactiveUserControl<DeviceDetectInputViewModel>
{
public DeviceDetectInputView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
@@ -11,57 +11,56 @@ using FluentAvalonia.UI.Controls;
using ReactiveUI;
using RGB.NET.Core;
namespace Artemis.UI.Screens.Device
namespace Artemis.UI.Screens.Device;
public class DeviceDetectInputViewModel : ContentDialogViewModelBase
{
public class DeviceDetectInputViewModel : ContentDialogViewModelBase
private readonly IInputService _inputService;
private readonly ListLedGroup _ledGroup;
private readonly INotificationService _notificationService;
private readonly IRgbService _rgbService;
public DeviceDetectInputViewModel(ArtemisDevice device, IInputService inputService, INotificationService notificationService, IRgbService rgbService)
{
private readonly IInputService _inputService;
private readonly INotificationService _notificationService;
private readonly IRgbService _rgbService;
private readonly ListLedGroup _ledGroup;
_inputService = inputService;
_notificationService = notificationService;
_rgbService = rgbService;
public DeviceDetectInputViewModel(ArtemisDevice device, IInputService inputService, INotificationService notificationService, IRgbService rgbService)
Device = device;
// Create a LED group way at the top
_ledGroup = new ListLedGroup(_rgbService.Surface, Device.Leds.Select(l => l.RgbLed))
{
_inputService = inputService;
_notificationService = notificationService;
_rgbService = rgbService;
Brush = new SolidColorBrush(new Color(255, 255, 0)),
ZIndex = 999
};
Device = device;
// Create a LED group way at the top
_ledGroup = new ListLedGroup(_rgbService.Surface, Device.Leds.Select(l => l.RgbLed))
{
Brush = new SolidColorBrush(new Color(255, 255, 0)),
ZIndex = 999
};
this.WhenActivated(disposables =>
{
_inputService.IdentifyDevice(device);
Observable.FromEventPattern(x => _inputService.DeviceIdentified += x, x => _inputService.DeviceIdentified -= x)
.Subscribe(_ => InputServiceOnDeviceIdentified())
.DisposeWith(disposables);
Disposable.Create(() =>
{
_inputService.StopIdentify();
_ledGroup.Detach();
}).DisposeWith(disposables);
});
}
public ArtemisDevice Device { get; }
public bool IsMouse => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse;
public bool MadeChanges { get; set; }
private void InputServiceOnDeviceIdentified()
this.WhenActivated(disposables =>
{
ContentDialog?.Hide(ContentDialogResult.Primary);
_notificationService.CreateNotification()
.WithMessage($"{Device.RgbDevice.DeviceInfo.DeviceName} identified 😁")
.WithSeverity(NotificationSeverity.Success)
.Show();
}
_inputService.IdentifyDevice(device);
Observable.FromEventPattern(x => _inputService.DeviceIdentified += x, x => _inputService.DeviceIdentified -= x)
.Subscribe(_ => InputServiceOnDeviceIdentified())
.DisposeWith(disposables);
Disposable.Create(() =>
{
_inputService.StopIdentify();
_ledGroup.Detach();
}).DisposeWith(disposables);
});
}
public ArtemisDevice Device { get; }
public bool IsMouse => Device.RgbDevice.DeviceInfo.DeviceType == RGBDeviceType.Mouse;
public bool MadeChanges { get; set; }
private void InputServiceOnDeviceIdentified()
{
ContentDialog?.Hide(ContentDialogResult.Primary);
_notificationService.CreateNotification()
.WithMessage($"{Device.RgbDevice.DeviceInfo.DeviceName} identified 😁")
.WithSeverity(NotificationSeverity.Success)
.Show();
}
}
@@ -1,5 +1,4 @@
using System;
using System.Collections.ObjectModel;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Disposables;
@@ -10,53 +9,51 @@ using Artemis.UI.Shared;
using ReactiveUI;
using RGB.NET.Core;
using SkiaSharp;
using ArtemisLed = Artemis.Core.ArtemisLed;
namespace Artemis.UI.Screens.Device
namespace Artemis.UI.Screens.Device;
public class DevicePropertiesViewModel : DialogViewModelBase<object>
{
public class DevicePropertiesViewModel : DialogViewModelBase<object>
public DevicePropertiesViewModel(ArtemisDevice device, ICoreService coreService, IDeviceVmFactory deviceVmFactory)
{
public DevicePropertiesViewModel(ArtemisDevice device, ICoreService coreService, IDeviceVmFactory deviceVmFactory)
Device = device;
SelectedLeds = new ObservableCollection<ArtemisLed>();
Tabs = new ObservableCollection<ActivatableViewModelBase>();
Tabs.Add(deviceVmFactory.DevicePropertiesTabViewModel(device));
Tabs.Add(deviceVmFactory.DeviceInfoTabViewModel(device));
if (Device.DeviceType == RGBDeviceType.Keyboard)
Tabs.Add(deviceVmFactory.InputMappingsTabViewModel(device, SelectedLeds));
Tabs.Add(deviceVmFactory.DeviceLedsTabViewModel(device, SelectedLeds));
this.WhenActivated(d =>
{
Device = device;
SelectedLeds = new ObservableCollection<ArtemisLed>();
Tabs = new ObservableCollection<ActivatableViewModelBase>();
coreService.FrameRendering += CoreServiceOnFrameRendering;
Disposable.Create(() => coreService.FrameRendering -= CoreServiceOnFrameRendering).DisposeWith(d);
});
Tabs.Add(deviceVmFactory.DevicePropertiesTabViewModel(device));
Tabs.Add(deviceVmFactory.DeviceInfoTabViewModel(device));
if (Device.DeviceType == RGBDeviceType.Keyboard)
Tabs.Add(deviceVmFactory.InputMappingsTabViewModel(device, SelectedLeds));
Tabs.Add(deviceVmFactory.DeviceLedsTabViewModel(device, SelectedLeds));
ClearSelectedLeds = ReactiveCommand.Create(ExecuteClearSelectedLeds);
}
this.WhenActivated(d =>
{
coreService.FrameRendering += CoreServiceOnFrameRendering;
Disposable.Create(() => coreService.FrameRendering -= CoreServiceOnFrameRendering).DisposeWith(d);
});
public ArtemisDevice Device { get; }
public ObservableCollection<ArtemisLed> SelectedLeds { get; }
public ObservableCollection<ActivatableViewModelBase> Tabs { get; }
ClearSelectedLeds = ReactiveCommand.Create(ExecuteClearSelectedLeds);
}
public ReactiveCommand<Unit, Unit> ClearSelectedLeds { get; }
public ArtemisDevice Device { get; }
public ObservableCollection<ArtemisLed> SelectedLeds { get; }
public ObservableCollection<ActivatableViewModelBase> Tabs { get; }
private void ExecuteClearSelectedLeds()
{
SelectedLeds.Clear();
}
public ReactiveCommand<Unit, Unit> ClearSelectedLeds { get; }
private void ExecuteClearSelectedLeds()
{
SelectedLeds.Clear();
}
private void CoreServiceOnFrameRendering(object? sender, FrameRenderingEventArgs e)
{
if (!SelectedLeds.Any())
return;
private void CoreServiceOnFrameRendering(object? sender, FrameRenderingEventArgs e)
{
if (!SelectedLeds.Any())
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);
}
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);
}
}
@@ -1,19 +1,17 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device
{
public partial class DeviceSettingsView : ReactiveUserControl<DeviceSettingsViewModel>
{
public DeviceSettingsView()
{
InitializeComponent();
}
namespace Artemis.UI.Screens.Device;
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public class DeviceSettingsView : ReactiveUserControl<DeviceSettingsViewModel>
{
public DeviceSettingsView()
{
InitializeComponent();
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
@@ -11,114 +11,113 @@ using Humanizer;
using ReactiveUI;
using RGB.NET.Core;
namespace Artemis.UI.Screens.Device
namespace Artemis.UI.Screens.Device;
public class DeviceSettingsViewModel : ActivatableViewModelBase
{
public class DeviceSettingsViewModel : ActivatableViewModelBase
private readonly IDeviceService _deviceService;
private readonly DevicesTabViewModel _devicesTabViewModel;
private readonly IDeviceVmFactory _deviceVmFactory;
private readonly IRgbService _rgbService;
private readonly IWindowService _windowService;
private bool _togglingDevice;
public DeviceSettingsViewModel(ArtemisDevice device, DevicesTabViewModel devicesTabViewModel, IDeviceService deviceService, IWindowService windowService, IDeviceVmFactory deviceVmFactory,
IRgbService rgbService)
{
private readonly IDeviceService _deviceService;
private readonly DevicesTabViewModel _devicesTabViewModel;
private readonly IDeviceVmFactory _deviceVmFactory;
private readonly IRgbService _rgbService;
private readonly IWindowService _windowService;
private bool _togglingDevice;
_devicesTabViewModel = devicesTabViewModel;
_deviceService = deviceService;
_windowService = windowService;
_deviceVmFactory = deviceVmFactory;
_rgbService = rgbService;
Device = device;
public DeviceSettingsViewModel(ArtemisDevice device, DevicesTabViewModel devicesTabViewModel, IDeviceService deviceService, IWindowService windowService, IDeviceVmFactory deviceVmFactory,
IRgbService rgbService)
{
_devicesTabViewModel = devicesTabViewModel;
_deviceService = deviceService;
_windowService = windowService;
_deviceVmFactory = deviceVmFactory;
_rgbService = rgbService;
Device = device;
Type = Device.DeviceType.ToString().Humanize();
Name = Device.RgbDevice.DeviceInfo.Model;
Manufacturer = Device.RgbDevice.DeviceInfo.Manufacturer;
Type = Device.DeviceType.ToString().Humanize();
Name = Device.RgbDevice.DeviceInfo.Model;
Manufacturer = Device.RgbDevice.DeviceInfo.Manufacturer;
DetectInput = ReactiveCommand.CreateFromTask(ExecuteDetectInput, this.WhenAnyValue(vm => vm.CanDetectInput));
}
DetectInput = ReactiveCommand.CreateFromTask(ExecuteDetectInput, this.WhenAnyValue(vm => vm.CanDetectInput));
}
public ArtemisDevice Device { get; }
public ArtemisDevice Device { get; }
public string Type { get; }
public string Name { get; }
public string Manufacturer { get; }
public string Type { get; }
public string Name { get; }
public string Manufacturer { get; }
public bool CanDetectInput => Device.DeviceType is RGBDeviceType.Keyboard or RGBDeviceType.Mouse;
public ReactiveCommand<Unit, Unit> DetectInput { get; }
public bool CanDetectInput => Device.DeviceType is RGBDeviceType.Keyboard or RGBDeviceType.Mouse;
public ReactiveCommand<Unit, Unit> DetectInput { get; }
public bool IsDeviceEnabled
{
get => Device.IsEnabled;
set => Dispatcher.UIThread.InvokeAsync(async () => await UpdateIsDeviceEnabled(value));
}
public bool IsDeviceEnabled
{
get => Device.IsEnabled;
set => Dispatcher.UIThread.InvokeAsync(async () => await UpdateIsDeviceEnabled(value));
}
public bool TogglingDevice
{
get => _togglingDevice;
set => RaiseAndSetIfChanged(ref _togglingDevice, value);
}
public bool TogglingDevice
{
get => _togglingDevice;
set => RaiseAndSetIfChanged(ref _togglingDevice, value);
}
public void IdentifyDevice()
{
_deviceService.IdentifyDevice(Device);
}
public void IdentifyDevice()
{
_deviceService.IdentifyDevice(Device);
}
public void OpenPluginDirectory()
{
Utilities.OpenFolder(Device.DeviceProvider.Plugin.Directory.FullName);
}
public void OpenPluginDirectory()
{
Utilities.OpenFolder(Device.DeviceProvider.Plugin.Directory.FullName);
}
public async Task ViewProperties()
{
await _windowService.ShowDialogAsync(_deviceVmFactory.DevicePropertiesViewModel(Device));
}
private async Task ExecuteDetectInput()
{
if (!CanDetectInput)
return;
private async Task ExecuteDetectInput()
{
if (!CanDetectInput)
return;
await _windowService.CreateContentDialog()
.WithTitle($"{Device.RgbDevice.DeviceInfo.DeviceName} - Detect input")
.WithViewModel<DeviceDetectInputViewModel>(out DeviceDetectInputViewModel? viewModel, ("device", Device))
.WithCloseButtonText("Cancel")
.ShowAsync();
await _windowService.CreateContentDialog()
.WithTitle($"{Device.RgbDevice.DeviceInfo.DeviceName} - Detect input")
.WithViewModel<DeviceDetectInputViewModel>(out DeviceDetectInputViewModel? viewModel, ("device", Device))
.WithCloseButtonText("Cancel")
.ShowAsync();
if (viewModel.MadeChanges)
_rgbService.SaveDevice(Device);
}
public async Task ViewProperties()
{
await _windowService.ShowDialogAsync(_deviceVmFactory.DevicePropertiesViewModel(Device));
}
private async Task UpdateIsDeviceEnabled(bool value)
{
if (TogglingDevice)
return;
try
{
TogglingDevice = true;
if (!value)
value = !await _devicesTabViewModel.ShowDeviceDisableDialog();
if (value)
_rgbService.EnableDevice(Device);
else
_rgbService.DisableDevice(Device);
this.RaisePropertyChanged(nameof(IsDeviceEnabled));
SaveDevice();
}
finally
{
TogglingDevice = false;
}
}
private void SaveDevice()
{
if (viewModel.MadeChanges)
_rgbService.SaveDevice(Device);
}
private async Task UpdateIsDeviceEnabled(bool value)
{
if (TogglingDevice)
return;
try
{
TogglingDevice = true;
if (!value)
value = !await _devicesTabViewModel.ShowDeviceDisableDialog();
if (value)
_rgbService.EnableDevice(Device);
else
_rgbService.DisableDevice(Device);
this.RaisePropertyChanged(nameof(IsDeviceEnabled));
SaveDevice();
}
finally
{
TogglingDevice = false;
}
}
private void SaveDevice()
{
_rgbService.SaveDevice(Device);
}
}
@@ -1,19 +1,17 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device
{
public partial class DeviceInfoTabView : ReactiveUserControl<DeviceInfoTabViewModel>
{
public DeviceInfoTabView()
{
InitializeComponent();
}
namespace Artemis.UI.Screens.Device;
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public class DeviceInfoTabView : ReactiveUserControl<DeviceInfoTabViewModel>
{
public DeviceInfoTabView()
{
InitializeComponent();
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
@@ -5,34 +5,33 @@ using Artemis.UI.Shared.Services;
using Avalonia;
using RGB.NET.Core;
namespace Artemis.UI.Screens.Device
namespace Artemis.UI.Screens.Device;
public class DeviceInfoTabViewModel : ActivatableViewModelBase
{
public class DeviceInfoTabViewModel : ActivatableViewModelBase
private readonly INotificationService _notificationService;
public DeviceInfoTabViewModel(ArtemisDevice device, INotificationService notificationService)
{
private readonly INotificationService _notificationService;
_notificationService = notificationService;
public DeviceInfoTabViewModel(ArtemisDevice device, INotificationService notificationService)
{
_notificationService = notificationService;
Device = device;
DisplayName = "Info";
Device = device;
DisplayName = "Info";
DefaultLayoutPath = Device.DeviceProvider.LoadLayout(Device).FilePath;
}
DefaultLayoutPath = Device.DeviceProvider.LoadLayout(Device).FilePath;
}
public bool IsKeyboard => Device.DeviceType == RGBDeviceType.Keyboard;
public ArtemisDevice Device { get; }
public bool IsKeyboard => Device.DeviceType == RGBDeviceType.Keyboard;
public ArtemisDevice Device { get; }
public string DefaultLayoutPath { get; }
public string DefaultLayoutPath { get; }
public async Task CopyToClipboard(string content)
{
if (Application.Current?.Clipboard == null)
return;
public async Task CopyToClipboard(string content)
{
if (Application.Current?.Clipboard == null)
return;
await Application.Current.Clipboard.SetTextAsync(content);
_notificationService.CreateNotification().WithMessage("Copied path to clipboard.").Show();
}
await Application.Current.Clipboard.SetTextAsync(content);
_notificationService.CreateNotification().WithMessage("Copied path to clipboard.").Show();
}
}
@@ -1,7 +1,6 @@
using System.Collections.ObjectModel;
using Artemis.Core;
using Artemis.UI.Shared;
using RGB.NET.Core;
namespace Artemis.UI.Screens.Device;
@@ -1,19 +1,17 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device
{
public partial class DeviceLedsTabView : ReactiveUserControl<DeviceLedsTabViewModel>
{
public DeviceLedsTabView()
{
InitializeComponent();
}
namespace Artemis.UI.Screens.Device;
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public class DeviceLedsTabView : ReactiveUserControl<DeviceLedsTabViewModel>
{
public DeviceLedsTabView()
{
InitializeComponent();
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
@@ -8,35 +8,34 @@ using Artemis.UI.Shared;
using DynamicData.Binding;
using ReactiveUI;
namespace Artemis.UI.Screens.Device
namespace Artemis.UI.Screens.Device;
public class DeviceLedsTabViewModel : ActivatableViewModelBase
{
public class DeviceLedsTabViewModel : ActivatableViewModelBase
private readonly ObservableCollection<ArtemisLed> _selectedLeds;
public DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds)
{
private readonly ObservableCollection<ArtemisLed> _selectedLeds;
_selectedLeds = selectedLeds;
public DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds)
{
_selectedLeds = selectedLeds;
Device = device;
DisplayName = "LEDs";
LedViewModels = new ObservableCollection<DeviceLedsTabLedViewModel>(Device.Leds.Select(l => new DeviceLedsTabLedViewModel(l, _selectedLeds)));
Device = device;
DisplayName = "LEDs";
LedViewModels = new ObservableCollection<DeviceLedsTabLedViewModel>(Device.Leds.Select(l => new DeviceLedsTabLedViewModel(l, _selectedLeds)));
this.WhenActivated(disposables => _selectedLeds.ToObservableChangeSet().Subscribe(_ => UpdateSelectedLeds()).DisposeWith(disposables));
}
this.WhenActivated(disposables => _selectedLeds.ToObservableChangeSet().Subscribe(_ => UpdateSelectedLeds()).DisposeWith(disposables));
}
public ArtemisDevice Device { get; }
public ObservableCollection<DeviceLedsTabLedViewModel> LedViewModels { get; }
public ArtemisDevice Device { get; }
public ObservableCollection<DeviceLedsTabLedViewModel> LedViewModels { get; }
private void SelectedLedsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateSelectedLeds();
}
private void SelectedLedsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
UpdateSelectedLeds();
}
private void UpdateSelectedLeds()
{
foreach (DeviceLedsTabLedViewModel deviceLedsTabLedViewModel in LedViewModels)
deviceLedsTabLedViewModel.Update();
}
private void UpdateSelectedLeds()
{
foreach (DeviceLedsTabLedViewModel deviceLedsTabLedViewModel in LedViewModels)
deviceLedsTabLedViewModel.Update();
}
}
@@ -5,11 +5,10 @@ using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using Avalonia.Threading;
using ReactiveUI;
namespace Artemis.UI.Screens.Device;
public partial class DeviceLogicalLayoutDialogView : ReactiveUserControl<DeviceLogicalLayoutDialogViewModel>
public class DeviceLogicalLayoutDialogView : ReactiveUserControl<DeviceLogicalLayoutDialogViewModel>
{
private readonly AutoCompleteBox _autoCompleteBox;
@@ -19,7 +18,7 @@ public partial class DeviceLogicalLayoutDialogView : ReactiveUserControl<DeviceL
_autoCompleteBox = this.Get<AutoCompleteBox>("RegionsAutoCompleteBox");
_autoCompleteBox.ItemFilter += SearchRegions;
Dispatcher.UIThread.InvokeAsync(DelayedAutoFocus);
}
@@ -9,6 +9,7 @@ using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using FluentAvalonia.UI.Controls;
using ReactiveUI;
using ContentDialogButton = Artemis.UI.Shared.Services.Builders.ContentDialogButton;
namespace Artemis.UI.Screens.Device;
@@ -25,15 +26,15 @@ public class DeviceLogicalLayoutDialogViewModel : ContentDialogViewModelBase
Device = device;
ApplyLogicalLayout = ReactiveCommand.Create(ExecuteApplyLogicalLayout, this.WhenAnyValue(vm => vm.SelectedRegion).Select(r => r != null));
Regions = new ObservableCollection<RegionInfo>(CultureInfo.GetCultures(CultureTypes.SpecificCultures)
.Where(c => c.LCID != LOCALE_INVARIANT &&
c.LCID != LOCALE_NEUTRAL &&
c.LCID != LOCALE_CUSTOM_DEFAULT &&
.Where(c => c.LCID != LOCALE_INVARIANT &&
c.LCID != LOCALE_NEUTRAL &&
c.LCID != LOCALE_CUSTOM_DEFAULT &&
!c.CultureTypes.HasFlag(CultureTypes.UserCustomCulture))
.Select(c => new RegionInfo(c.LCID))
.GroupBy(r => r.EnglishName)
.Select(g => g.First())
.OrderBy(r => r.EnglishName));
// Default to US/international
SelectedRegion = Regions.FirstOrDefault(r => r.TwoLetterISORegionName == "US");
}
@@ -49,6 +50,19 @@ public class DeviceLogicalLayoutDialogViewModel : ContentDialogViewModelBase
set => RaiseAndSetIfChanged(ref _selectedRegion, value);
}
public static async Task<bool> SelectLogicalLayout(IWindowService windowService, ArtemisDevice device)
{
await windowService.CreateContentDialog()
.WithTitle("Select logical layout")
.WithViewModel(out DeviceLogicalLayoutDialogViewModel vm, ("device", device))
.WithCloseButtonText("Cancel")
.WithDefaultButton(ContentDialogButton.Primary)
.HavingPrimaryButton(b => b.WithText("Select").WithCommand(vm.ApplyLogicalLayout))
.ShowAsync();
return vm.Applied;
}
private void ExecuteApplyLogicalLayout()
{
if (SelectedRegion == null)
@@ -58,18 +72,4 @@ public class DeviceLogicalLayoutDialogViewModel : ContentDialogViewModelBase
Applied = true;
ContentDialog?.Hide(ContentDialogResult.Primary);
}
public static async Task<bool> SelectLogicalLayout(IWindowService windowService, ArtemisDevice device)
{
await windowService.CreateContentDialog()
.WithTitle("Select logical layout")
.WithViewModel(out DeviceLogicalLayoutDialogViewModel vm, ("device", device))
.WithCloseButtonText("Cancel")
.WithDefaultButton(Shared.Services.Builders.ContentDialogButton.Primary)
.HavingPrimaryButton(b => b.WithText("Select").WithCommand(vm.ApplyLogicalLayout))
.ShowAsync();
return vm.Applied;
}
}
@@ -1,11 +1,9 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device;
public partial class DevicePhysicalLayoutDialogView : ReactiveUserControl<DevicePhysicalLayoutDialogViewModel>
public class DevicePhysicalLayoutDialogView : ReactiveUserControl<DevicePhysicalLayoutDialogViewModel>
{
public DevicePhysicalLayoutDialogView()
{
@@ -21,13 +21,6 @@ public class DevicePhysicalLayoutDialogViewModel : ContentDialogViewModelBase
public ReactiveCommand<string, Unit> ApplyPhysicalLayout { get; }
public bool Applied { get; set; }
private void ExecuteApplyPhysicalLayout(string physicalLayout)
{
Device.PhysicalLayout = Enum.Parse<KeyboardLayoutType>(physicalLayout);
Applied = true;
ContentDialog?.Hide(ContentDialogResult.Primary);
}
public static async Task<bool> SelectPhysicalLayout(IWindowService windowService, ArtemisDevice device)
{
await windowService.CreateContentDialog()
@@ -38,4 +31,11 @@ public class DevicePhysicalLayoutDialogViewModel : ContentDialogViewModelBase
return vm.Applied;
}
private void ExecuteApplyPhysicalLayout(string physicalLayout)
{
Device.PhysicalLayout = Enum.Parse<KeyboardLayoutType>(physicalLayout);
Applied = true;
ContentDialog?.Hide(ContentDialogResult.Primary);
}
}
@@ -2,23 +2,22 @@ using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device
namespace Artemis.UI.Screens.Device;
public class DevicePropertiesTabView : ReactiveUserControl<DevicePropertiesTabViewModel>
{
public partial class DevicePropertiesTabView : ReactiveUserControl<DevicePropertiesTabViewModel>
public DevicePropertiesTabView()
{
public DevicePropertiesTabView()
{
InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
ViewModel?.BrowseCustomLayout();
}
InitializeComponent();
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void InputElement_OnPointerReleased(object? sender, PointerReleasedEventArgs e)
{
ViewModel?.BrowseCustomLayout();
}
}
@@ -11,270 +11,269 @@ using Artemis.UI.Shared.Services.Builders;
using ReactiveUI;
using SkiaSharp;
namespace Artemis.UI.Screens.Device
namespace Artemis.UI.Screens.Device;
public class DevicePropertiesTabViewModel : ActivatableViewModelBase
{
public class DevicePropertiesTabViewModel : ActivatableViewModelBase
private readonly List<DeviceCategory> _categories;
private readonly ICoreService _coreService;
private readonly float _initialBlueScale;
private readonly float _initialGreenScale;
private readonly float _initialRedScale;
private readonly INotificationService _notificationService;
private readonly IRgbService _rgbService;
private readonly IWindowService _windowService;
private float _blueScale;
private SKColor _currentColor;
private bool _displayOnDevices;
private float _greenScale;
private float _redScale;
private int _rotation;
private float _scale;
private int _x;
private int _y;
public DevicePropertiesTabViewModel(ArtemisDevice device, ICoreService coreService, IRgbService rgbService, IWindowService windowService, INotificationService notificationService)
{
private readonly List<DeviceCategory> _categories;
private readonly ICoreService _coreService;
private readonly float _initialBlueScale;
private readonly float _initialGreenScale;
private readonly float _initialRedScale;
private readonly INotificationService _notificationService;
private readonly IRgbService _rgbService;
private readonly IWindowService _windowService;
private float _blueScale;
private SKColor _currentColor;
private bool _displayOnDevices;
private float _greenScale;
private float _redScale;
private int _rotation;
private float _scale;
private int _x;
private int _y;
_coreService = coreService;
_rgbService = rgbService;
_windowService = windowService;
_notificationService = notificationService;
_categories = new List<DeviceCategory>(device.Categories);
public DevicePropertiesTabViewModel(ArtemisDevice device, ICoreService coreService, IRgbService rgbService, IWindowService windowService, INotificationService notificationService)
Device = device;
DisplayName = "Properties";
X = (int) Device.X;
Y = (int) Device.Y;
Scale = Device.Scale;
Rotation = (int) Device.Rotation;
RedScale = Device.RedScale * 100f;
GreenScale = Device.GreenScale * 100f;
BlueScale = Device.BlueScale * 100f;
CurrentColor = SKColors.White;
// 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;
this.WhenAnyValue(x => x.RedScale, x => x.GreenScale, x => x.BlueScale).Subscribe(_ => ApplyScaling());
this.WhenActivated(d =>
{
_coreService = coreService;
_rgbService = rgbService;
_windowService = windowService;
_notificationService = notificationService;
_categories = new List<DeviceCategory>(device.Categories);
Device.PropertyChanged += DeviceOnPropertyChanged;
_coreService.FrameRendering += OnFrameRendering;
Device = device;
DisplayName = "Properties";
X = (int) Device.X;
Y = (int) Device.Y;
Scale = Device.Scale;
Rotation = (int) Device.Rotation;
RedScale = Device.RedScale * 100f;
GreenScale = Device.GreenScale * 100f;
BlueScale = Device.BlueScale * 100f;
CurrentColor = SKColors.White;
// 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;
this.WhenAnyValue(x => x.RedScale, x => x.GreenScale, x => x.BlueScale).Subscribe(_ => ApplyScaling());
this.WhenActivated(d =>
Disposable.Create(() =>
{
Device.PropertyChanged += DeviceOnPropertyChanged;
_coreService.FrameRendering += OnFrameRendering;
_coreService.FrameRendering -= OnFrameRendering;
Device.PropertyChanged -= DeviceOnPropertyChanged;
}).DisposeWith(d);
});
}
Disposable.Create(() =>
{
_coreService.FrameRendering -= OnFrameRendering;
Device.PropertyChanged -= DeviceOnPropertyChanged;
}).DisposeWith(d);
});
}
public ArtemisDevice Device { get; }
public ArtemisDevice Device { get; }
public int X
{
get => _x;
set => RaiseAndSetIfChanged(ref _x, value);
}
public int X
public int Y
{
get => _y;
set => RaiseAndSetIfChanged(ref _y, value);
}
public float Scale
{
get => _scale;
set => RaiseAndSetIfChanged(ref _scale, value);
}
public int Rotation
{
get => _rotation;
set => RaiseAndSetIfChanged(ref _rotation, value);
}
public float RedScale
{
get => _redScale;
set => RaiseAndSetIfChanged(ref _redScale, value);
}
public float GreenScale
{
get => _greenScale;
set => RaiseAndSetIfChanged(ref _greenScale, value);
}
public float BlueScale
{
get => _blueScale;
set => RaiseAndSetIfChanged(ref _blueScale, value);
}
public SKColor CurrentColor
{
get => _currentColor;
set => RaiseAndSetIfChanged(ref _currentColor, value);
}
public bool DisplayOnDevices
{
get => _displayOnDevices;
set => RaiseAndSetIfChanged(ref _displayOnDevices, value);
}
// This solution won't scale well but I don't expect there to be many more categories.
// If for some reason there will be, dynamically creating a view model per category may be more appropriate
public bool HasDeskCategory
{
get => GetCategory(DeviceCategory.Desk);
set => SetCategory(DeviceCategory.Desk, value);
}
public bool HasMonitorCategory
{
get => GetCategory(DeviceCategory.Monitor);
set => SetCategory(DeviceCategory.Monitor, value);
}
public bool HasCaseCategory
{
get => GetCategory(DeviceCategory.Case);
set => SetCategory(DeviceCategory.Case, value);
}
public bool HasRoomCategory
{
get => GetCategory(DeviceCategory.Room);
set => SetCategory(DeviceCategory.Room, value);
}
public bool HasPeripheralsCategory
{
get => GetCategory(DeviceCategory.Peripherals);
set => SetCategory(DeviceCategory.Peripherals, value);
}
public bool RequiresManualSetup => !Device.DeviceProvider.CanDetectPhysicalLayout || !Device.DeviceProvider.CanDetectLogicalLayout;
public void ApplyScaling()
{
Device.RedScale = RedScale / 100f;
Device.GreenScale = GreenScale / 100f;
Device.BlueScale = BlueScale / 100f;
_rgbService.FlushLeds = true;
}
public void ClearCustomLayout()
{
Device.CustomLayoutPath = null;
_notificationService.CreateNotification()
.WithMessage("Cleared imported layout.")
.WithSeverity(NotificationSeverity.Informational);
}
public async Task BrowseCustomLayout()
{
string[]? files = await _windowService.CreateOpenFileDialog()
.WithTitle("Select device layout file")
.HavingFilter(f => f.WithName("Layout files").WithExtension("xml"))
.ShowAsync();
if (files?.Length > 0)
{
get => _x;
set => RaiseAndSetIfChanged(ref _x, value);
}
public int Y
{
get => _y;
set => RaiseAndSetIfChanged(ref _y, value);
}
public float Scale
{
get => _scale;
set => RaiseAndSetIfChanged(ref _scale, value);
}
public int Rotation
{
get => _rotation;
set => RaiseAndSetIfChanged(ref _rotation, value);
}
public float RedScale
{
get => _redScale;
set => RaiseAndSetIfChanged(ref _redScale, value);
}
public float GreenScale
{
get => _greenScale;
set => RaiseAndSetIfChanged(ref _greenScale, value);
}
public float BlueScale
{
get => _blueScale;
set => RaiseAndSetIfChanged(ref _blueScale, value);
}
public SKColor CurrentColor
{
get => _currentColor;
set => RaiseAndSetIfChanged(ref _currentColor, value);
}
public bool DisplayOnDevices
{
get => _displayOnDevices;
set => RaiseAndSetIfChanged(ref _displayOnDevices, value);
}
// This solution won't scale well but I don't expect there to be many more categories.
// If for some reason there will be, dynamically creating a view model per category may be more appropriate
public bool HasDeskCategory
{
get => GetCategory(DeviceCategory.Desk);
set => SetCategory(DeviceCategory.Desk, value);
}
public bool HasMonitorCategory
{
get => GetCategory(DeviceCategory.Monitor);
set => SetCategory(DeviceCategory.Monitor, value);
}
public bool HasCaseCategory
{
get => GetCategory(DeviceCategory.Case);
set => SetCategory(DeviceCategory.Case, value);
}
public bool HasRoomCategory
{
get => GetCategory(DeviceCategory.Room);
set => SetCategory(DeviceCategory.Room, value);
}
public bool HasPeripheralsCategory
{
get => GetCategory(DeviceCategory.Peripherals);
set => SetCategory(DeviceCategory.Peripherals, value);
}
public bool RequiresManualSetup => !Device.DeviceProvider.CanDetectPhysicalLayout || !Device.DeviceProvider.CanDetectLogicalLayout;
public void ApplyScaling()
{
Device.RedScale = RedScale / 100f;
Device.GreenScale = GreenScale / 100f;
Device.BlueScale = BlueScale / 100f;
_rgbService.FlushLeds = true;
}
public void ClearCustomLayout()
{
Device.CustomLayoutPath = null;
Device.CustomLayoutPath = files[0];
_notificationService.CreateNotification()
.WithMessage("Cleared imported layout.")
.WithTitle("Imported layout")
.WithMessage($"File loaded from {files[0]}")
.WithSeverity(NotificationSeverity.Informational);
}
}
public async Task BrowseCustomLayout()
{
string[]? files = await _windowService.CreateOpenFileDialog()
.WithTitle("Select device layout file")
.HavingFilter(f => f.WithName("Layout files").WithExtension("xml"))
.ShowAsync();
public async Task RestartSetup()
{
if (!RequiresManualSetup)
return;
if (!Device.DeviceProvider.CanDetectPhysicalLayout && !await DevicePhysicalLayoutDialogViewModel.SelectPhysicalLayout(_windowService, Device))
return;
if (!Device.DeviceProvider.CanDetectLogicalLayout && !await DeviceLogicalLayoutDialogViewModel.SelectLogicalLayout(_windowService, Device))
return;
if (files?.Length > 0)
{
Device.CustomLayoutPath = files[0];
_notificationService.CreateNotification()
.WithTitle("Imported layout")
.WithMessage($"File loaded from {files[0]}")
.WithSeverity(NotificationSeverity.Informational);
}
}
await Task.Delay(400);
_rgbService.SaveDevice(Device);
_rgbService.ApplyBestDeviceLayout(Device);
}
public async Task RestartSetup()
{
if (!RequiresManualSetup)
return;
if (!Device.DeviceProvider.CanDetectPhysicalLayout && !await DevicePhysicalLayoutDialogViewModel.SelectPhysicalLayout(_windowService, Device))
return;
if (!Device.DeviceProvider.CanDetectLogicalLayout && !await DeviceLogicalLayoutDialogViewModel.SelectLogicalLayout(_windowService, Device))
return;
public async Task Apply()
{
// TODO: Validation
await Task.Delay(400);
_rgbService.SaveDevice(Device);
_rgbService.ApplyBestDeviceLayout(Device);
}
_coreService.ProfileRenderingDisabled = true;
await Task.Delay(100);
public async Task Apply()
{
// TODO: Validation
Device.X = X;
Device.Y = Y;
Device.Scale = Scale;
Device.Rotation = Rotation;
Device.RedScale = RedScale / 100f;
Device.GreenScale = GreenScale / 100f;
Device.BlueScale = BlueScale / 100f;
Device.Categories.Clear();
foreach (DeviceCategory deviceCategory in _categories)
Device.Categories.Add(deviceCategory);
_coreService.ProfileRenderingDisabled = true;
await Task.Delay(100);
_rgbService.SaveDevice(Device);
Device.X = X;
Device.Y = Y;
Device.Scale = Scale;
Device.Rotation = Rotation;
Device.RedScale = RedScale / 100f;
Device.GreenScale = GreenScale / 100f;
Device.BlueScale = BlueScale / 100f;
Device.Categories.Clear();
foreach (DeviceCategory deviceCategory in _categories)
Device.Categories.Add(deviceCategory);
_coreService.ProfileRenderingDisabled = false;
}
_rgbService.SaveDevice(Device);
public void Reset()
{
HasDeskCategory = Device.Categories.Contains(DeviceCategory.Desk);
HasMonitorCategory = Device.Categories.Contains(DeviceCategory.Monitor);
HasCaseCategory = Device.Categories.Contains(DeviceCategory.Case);
HasRoomCategory = Device.Categories.Contains(DeviceCategory.Room);
HasPeripheralsCategory = Device.Categories.Contains(DeviceCategory.Peripherals);
_coreService.ProfileRenderingDisabled = false;
}
RedScale = _initialRedScale * 100;
GreenScale = _initialGreenScale * 100;
BlueScale = _initialBlueScale * 100;
}
public void Reset()
{
HasDeskCategory = Device.Categories.Contains(DeviceCategory.Desk);
HasMonitorCategory = Device.Categories.Contains(DeviceCategory.Monitor);
HasCaseCategory = Device.Categories.Contains(DeviceCategory.Case);
HasRoomCategory = Device.Categories.Contains(DeviceCategory.Room);
HasPeripheralsCategory = Device.Categories.Contains(DeviceCategory.Peripherals);
private bool GetCategory(DeviceCategory category)
{
return _categories.Contains(category);
}
RedScale = _initialRedScale * 100;
GreenScale = _initialGreenScale * 100;
BlueScale = _initialBlueScale * 100;
}
private void SetCategory(DeviceCategory category, bool value)
{
if (value && !_categories.Contains(category))
_categories.Add(category);
else if (!value)
_categories.Remove(category);
private bool GetCategory(DeviceCategory category)
{
return _categories.Contains(category);
}
this.RaisePropertyChanged($"Has{category}Category");
}
private void SetCategory(DeviceCategory category, bool value)
{
if (value && !_categories.Contains(category))
_categories.Add(category);
else if (!value)
_categories.Remove(category);
private void OnFrameRendering(object? sender, FrameRenderingEventArgs e)
{
if (!_displayOnDevices)
return;
this.RaisePropertyChanged($"Has{category}Category");
}
using SKPaint overlayPaint = new() {Color = CurrentColor};
e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint);
}
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);
}
private void DeviceOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout))
Task.Run(() => _rgbService.ApplyBestDeviceLayout(Device));
}
private void DeviceOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout))
Task.Run(() => _rgbService.ApplyBestDeviceLayout(Device));
}
}
@@ -1,19 +1,17 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device
{
public partial class InputMappingsTabView : ReactiveUserControl<InputMappingsTabViewModel>
{
public InputMappingsTabView()
{
InitializeComponent();
}
namespace Artemis.UI.Screens.Device;
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public class InputMappingsTabView : ReactiveUserControl<InputMappingsTabViewModel>
{
public InputMappingsTabView()
{
InitializeComponent();
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
@@ -1,5 +1,4 @@
using System;
using System.Collections.ObjectModel;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Reactive.Disposables;
@@ -10,92 +9,91 @@ using Artemis.UI.Shared;
using ReactiveUI;
using RGB.NET.Core;
namespace Artemis.UI.Screens.Device
namespace Artemis.UI.Screens.Device;
public class InputMappingsTabViewModel : ActivatableViewModelBase
{
public class InputMappingsTabViewModel : ActivatableViewModelBase
private readonly IInputService _inputService;
private readonly IRgbService _rgbService;
private readonly ObservableCollection<ArtemisLed> _selectedLeds;
private ArtemisLed? _selectedLed;
public InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds, IRgbService rgbService, IInputService inputService)
{
private readonly IRgbService _rgbService;
private readonly IInputService _inputService;
private readonly ObservableCollection<ArtemisLed> _selectedLeds;
private ArtemisLed? _selectedLed;
if (device.DeviceType != RGBDeviceType.Keyboard)
throw new ArtemisUIException("The input mappings tab only supports keyboards");
public InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds, IRgbService rgbService, IInputService inputService)
_rgbService = rgbService;
_inputService = inputService;
_selectedLeds = selectedLeds;
Device = device;
DisplayName = "Input Mappings";
InputMappings = new ObservableCollection<(ArtemisLed, ArtemisLed)>();
this.WhenActivated(d =>
{
if (device.DeviceType != RGBDeviceType.Keyboard)
throw new ArtemisUIException("The input mappings tab only supports keyboards");
_selectedLeds.CollectionChanged += SelectedLedsOnCollectionChanged;
_inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp;
UpdateInputMappings();
_rgbService = rgbService;
_inputService = inputService;
_selectedLeds = selectedLeds;
Device = device;
DisplayName = "Input Mappings";
InputMappings = new ObservableCollection<(ArtemisLed, ArtemisLed)>();
this.WhenActivated(d =>
Disposable.Create(() =>
{
_selectedLeds.CollectionChanged += SelectedLedsOnCollectionChanged;
_inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp;
UpdateInputMappings();
Disposable.Create(() =>
{
_selectedLeds.CollectionChanged -= SelectedLedsOnCollectionChanged;
_inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp;
InputMappings.Clear();
}).DisposeWith(d);
});
}
public ArtemisDevice Device { get; }
public ArtemisLed? SelectedLed
{
get => _selectedLed;
set => RaiseAndSetIfChanged(ref _selectedLed, value);
}
public ObservableCollection<(ArtemisLed, ArtemisLed)> InputMappings { get; }
public void DeleteMapping((ArtemisLed, ArtemisLed) inputMapping)
{
Device.InputMappings.Remove(inputMapping.Item1);
UpdateInputMappings();
}
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
{
if (SelectedLed == null || e.Led == null)
return;
// Locate the original LED the same way the InputService did it, but supply false to Device.GetLed
bool foundLedId = InputKeyUtilities.KeyboardKeyLedIdMap.TryGetValue(e.Key, out LedId ledId);
if (!foundLedId)
return;
ArtemisLed? artemisLed = Device.GetLed(ledId, false);
if (artemisLed == null)
return;
// Apply the new LED mapping
Device.InputMappings[SelectedLed] = artemisLed;
_rgbService.SaveDevice(Device);
_selectedLeds.Clear();
UpdateInputMappings();
}
private void UpdateInputMappings()
{
if (InputMappings.Any())
_selectedLeds.CollectionChanged -= SelectedLedsOnCollectionChanged;
_inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp;
InputMappings.Clear();
}).DisposeWith(d);
});
}
foreach ((ArtemisLed, ArtemisLed) tuple in Device.InputMappings.Select(m => (m.Key, m.Value)))
InputMappings.Add(tuple);
}
public ArtemisDevice Device { get; }
private void SelectedLedsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
SelectedLed = _selectedLeds.FirstOrDefault();
}
public ArtemisLed? SelectedLed
{
get => _selectedLed;
set => RaiseAndSetIfChanged(ref _selectedLed, value);
}
public ObservableCollection<(ArtemisLed, ArtemisLed)> InputMappings { get; }
public void DeleteMapping((ArtemisLed, ArtemisLed) inputMapping)
{
Device.InputMappings.Remove(inputMapping.Item1);
UpdateInputMappings();
}
private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e)
{
if (SelectedLed == null || e.Led == null)
return;
// Locate the original LED the same way the InputService did it, but supply false to Device.GetLed
bool foundLedId = InputKeyUtilities.KeyboardKeyLedIdMap.TryGetValue(e.Key, out LedId ledId);
if (!foundLedId)
return;
ArtemisLed? artemisLed = Device.GetLed(ledId, false);
if (artemisLed == null)
return;
// Apply the new LED mapping
Device.InputMappings[SelectedLed] = artemisLed;
_rgbService.SaveDevice(Device);
_selectedLeds.Clear();
UpdateInputMappings();
}
private void UpdateInputMappings()
{
if (InputMappings.Any())
InputMappings.Clear();
foreach ((ArtemisLed, ArtemisLed) tuple in Device.InputMappings.Select(m => (m.Key, m.Value)))
InputMappings.Add(tuple);
}
private void SelectedLedsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
SelectedLed = _selectedLeds.FirstOrDefault();
}
}