Devices - Reworking layout loading

This commit is contained in:
RobertBeekman committed 2024-01-09 21:27:51 +01:00
1 parent 9393bf2b68
commit e8590abd61
57 files changed
+824 -349

No files matched your search

@@ -5,9 +5,10 @@
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
xmlns:general="clr-namespace:Artemis.UI.Screens.Device.General"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="650"
x:Class="Artemis.UI.Screens.Device.DeviceGeneralTabView"
x:DataType="device:DeviceGeneralTabViewModel">
x:Class="Artemis.UI.Screens.Device.General.DeviceGeneralTabView"
x:DataType="general:DeviceGeneralTabViewModel">
<UserControl.Resources>
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
</UserControl.Resources>
@@ -1,7 +1,6 @@
using Avalonia.Controls;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.General;
public partial class DeviceGeneralTabView : ReactiveUserControl<DeviceGeneralTabViewModel>
{
public DeviceGeneralTabView()
@@ -4,6 +4,7 @@ using System.Reactive.Disposables;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.Device.Layout;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using PropertyChanged.SourceGenerator;
@@ -11,7 +12,7 @@ using ReactiveUI;
using RGB.NET.Core;
using SkiaSharp;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.General;
public partial class DeviceGeneralTabViewModel : ActivatableViewModelBase
{
@@ -56,7 +57,7 @@ public partial class DeviceGeneralTabViewModel : ActivatableViewModelBase
_initialGreenScale = Device.GreenScale;
_initialBlueScale = Device.BlueScale;
this.WhenAnyValue(x => x.RedScale, x => x.GreenScale, x => x.BlueScale).Subscribe(_ => ApplyScaling());
this.WhenAnyValue<DeviceGeneralTabViewModel, float, float, float>(x => x.RedScale, x => x.GreenScale, x => x.BlueScale).Subscribe(_ => ApplyScaling());
this.WhenActivated(d =>
{
@@ -127,12 +128,12 @@ public partial class DeviceGeneralTabViewModel : ActivatableViewModelBase
return;
if (!Device.DeviceProvider.CanDetectPhysicalLayout && !await DevicePhysicalLayoutDialogViewModel.SelectPhysicalLayout(_windowService, Device))
return;
if (!Device.DeviceProvider.CanDetectLogicalLayout && !await DeviceLogicalLayoutDialogViewModel.SelectLogicalLayout(_windowService, Device))
if (!Device.DeviceProvider.CanDetectLogicalLayout && !await Layout.DeviceLogicalLayoutDialogViewModel.SelectLogicalLayout(_windowService, Device))
return;
await Task.Delay(400);
_deviceService.SaveDevice(Device);
_deviceService.ApplyDeviceLayout(Device, Device.GetBestDeviceLayout());
_deviceService.LoadDeviceLayout(Device);
}
private void Apply()
@@ -4,9 +4,10 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:inputMappings="clr-namespace:Artemis.UI.Screens.Device.InputMappings"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Device.InputMappingsTabView"
x:DataType="device:InputMappingsTabViewModel">
x:Class="Artemis.UI.Screens.Device.InputMappings.InputMappingsTabView"
x:DataType="inputMappings:InputMappingsTabViewModel">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Grid RowDefinitions="Auto,Auto,*">
<StackPanel Grid.Row="0">
@@ -1,7 +1,6 @@
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.InputMappings;
public partial class InputMappingsTabView : ReactiveUserControl<InputMappingsTabViewModel>
{
@@ -6,13 +6,12 @@ using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Exceptions;
using Artemis.UI.Shared;
using HidSharp.Reports.Units;
using PropertyChanged.SourceGenerator;
using ReactiveUI;
using RGB.NET.Core;
using Unit = System.Reactive.Unit;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.InputMappings;
public partial class InputMappingsTabViewModel : ActivatableViewModelBase
{
@@ -5,9 +5,12 @@
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
xmlns:providers="clr-namespace:Artemis.Core.Providers;assembly=Artemis.Core"
xmlns:layout="clr-namespace:Artemis.UI.Screens.Device.Layout"
xmlns:layoutProviders="clr-namespace:Artemis.UI.Screens.Device.Layout.LayoutProviders"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800"
x:Class="Artemis.UI.Screens.Device.DeviceLayoutTabView"
x:DataType="device:DeviceLayoutTabViewModel">
x:Class="Artemis.UI.Screens.Device.Layout.DeviceLayoutTabView"
x:DataType="layout:DeviceLayoutTabViewModel">
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Border Classes="card" Margin="5">
<Grid RowDefinitions="*,Auto">
@@ -28,6 +31,7 @@
</Button>
</StackPanel>
</Grid>
<Border Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Row="1" Grid.Column="0">
@@ -45,28 +49,43 @@
</Button>
</StackPanel>
</Grid>
<Border Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<Grid RowDefinitions="*,*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Row="1" Grid.Column="0">
<TextBlock Text="Disable default layout" />
<TextBlock Classes="subtitle" FontSize="12" Text="With this checked, Artemis will not load a layout for this device unless you specifically provide one." />
<TextBlock Text="Layout provider" />
<TextBlock Classes="subtitle" FontSize="12" Text="Choose between different ways to load a layout for this device." />
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center">
<CheckBox HorizontalAlignment="Right" Margin="0,0,-10,0" IsChecked="{CompiledBinding Device.DisableDefaultLayout}"/>
</StackPanel>
</Grid>
<Border Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Row="1" Grid.Column="0">
<TextBlock Text="Custom layout path" />
<TextBlock Classes="subtitle" FontSize="12" Text="{CompiledBinding CustomLayoutPath, TargetNullValue=None}"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
<Button Content="Clear" Command="{CompiledBinding ClearCustomLayout}" IsEnabled="{CompiledBinding HasCustomLayout}" />
<!-- 5 pixels of margin between the buttons -->
<Button Margin="5,0,0,0" Content="Browse" Command="{CompiledBinding BrowseCustomLayout}" />
<StackPanel.Styles>
<Style Selector="ComboBox.layoutProvider /template/ ContentControl#ContentPresenter">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate x:DataType="layoutProviders:ILayoutProviderViewModel">
<TextBlock Text="{CompiledBinding Name}" TextWrapping="Wrap" MaxWidth="350" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Styles>
<ComboBox Classes="layoutProvider"
Width="150"
SelectedItem="{CompiledBinding SelectedLayoutProvider}"
ItemsSource="{CompiledBinding LayoutProviders}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="layoutProviders:ILayoutProviderViewModel">
<StackPanel>
<TextBlock Text="{CompiledBinding Name}" TextWrapping="Wrap" MaxWidth="350" />
<TextBlock Classes="subtitle" Text="{CompiledBinding Description}" TextWrapping="Wrap" MaxWidth="350" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Grid>
<ContentControl Content="{CompiledBinding SelectedLayoutProvider}" ClipToBounds="False"></ContentControl>
<Border Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Row="1" Grid.Column="0">
@@ -2,7 +2,7 @@
using Avalonia.Interactivity;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Layout;
public partial class DeviceLayoutTabView : ReactiveUserControl<DeviceLayoutTabViewModel>
{
@@ -1,81 +1,52 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.Device.Layout.LayoutProviders;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
using Avalonia.Controls;
using ReactiveUI;
using PropertyChanged.SourceGenerator;
using RGB.NET.Layout;
using SkiaSharp;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Layout;
public class DeviceLayoutTabViewModel : ActivatableViewModelBase
public partial class DeviceLayoutTabViewModel : ActivatableViewModelBase
{
[Notify] private ILayoutProviderViewModel? _selectedLayoutProvider;
private readonly IWindowService _windowService;
private readonly INotificationService _notificationService;
private readonly IDeviceService _deviceService;
public DeviceLayoutTabViewModel(IWindowService windowService, INotificationService notificationService, IDeviceService deviceService, ArtemisDevice device)
public DeviceLayoutTabViewModel(IWindowService windowService, INotificationService notificationService, ArtemisDevice device, List<ILayoutProviderViewModel> layoutProviders)
{
_windowService = windowService;
_notificationService = notificationService;
_deviceService = deviceService;
Device = device;
DisplayName = "Layout";
DefaultLayoutPath = Device.DeviceProvider.LoadLayout(Device).FilePath;
this.WhenActivated(d =>
LayoutProviders = new ObservableCollection<ILayoutProviderViewModel>(layoutProviders);
foreach (ILayoutProviderViewModel layoutProviderViewModel in layoutProviders)
{
Device.PropertyChanged += DeviceOnPropertyChanged;
Disposable.Create(() => Device.PropertyChanged -= DeviceOnPropertyChanged).DisposeWith(d);
});
layoutProviderViewModel.Device = Device;
if (layoutProviderViewModel.IsMatch(Device))
SelectedLayoutProvider = layoutProviderViewModel;
}
}
public ArtemisDevice Device { get; }
public ObservableCollection<ILayoutProviderViewModel> LayoutProviders { get; set; }
public string DefaultLayoutPath { get; }
public string? ImagePath => Device.Layout?.Image?.LocalPath;
public string? CustomLayoutPath => Device.CustomLayoutPath;
public bool HasCustomLayout => Device.CustomLayoutPath != null;
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)
{
Device.CustomLayoutPath = files[0];
_notificationService.CreateNotification()
.WithTitle("Imported layout")
.WithMessage($"File loaded from {files[0]}")
.WithSeverity(NotificationSeverity.Informational);
}
}
public async Task ExportLayout()
{
string fileName = Device.DeviceProvider.GetDeviceLayoutName(Device);
@@ -145,19 +116,4 @@ public class DeviceLayoutTabViewModel : ActivatableViewModelBase
.WithSeverity(NotificationSeverity.Informational)
.Show();
}
private void DeviceOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName is nameof(Device.CustomLayoutPath) or nameof(Device.DisableDefaultLayout))
{
Task.Run(() =>
{
_deviceService.ApplyDeviceLayout(Device, Device.GetBestDeviceLayout());
_deviceService.SaveDevice(Device);
});
this.RaisePropertyChanged(nameof(CustomLayoutPath));
this.RaisePropertyChanged(nameof(HasCustomLayout));
}
}
}
@@ -4,9 +4,10 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
xmlns:globalization="clr-namespace:System.Globalization;assembly=System.Runtime"
xmlns:layout="clr-namespace:Artemis.UI.Screens.Device.Layout"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Device.DeviceLogicalLayoutDialogView"
x:DataType="device:DeviceLogicalLayoutDialogViewModel">
x:Class="Artemis.UI.Screens.Device.Layout.DeviceLogicalLayoutDialogView"
x:DataType="layout:DeviceLogicalLayoutDialogViewModel">
<StackPanel>
<TextBlock TextWrapping="Wrap">Artemis couldn't automatically determine the logical layout of your</TextBlock>
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.DeviceName, Mode=OneWay}" />
@@ -1,12 +1,10 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using Avalonia.Threading;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Layout;
public partial class DeviceLogicalLayoutDialogView : ReactiveUserControl<DeviceLogicalLayoutDialogViewModel>
{
@@ -12,7 +12,7 @@ using PropertyChanged.SourceGenerator;
using ReactiveUI;
using ContentDialogButton = Artemis.UI.Shared.Services.Builders.ContentDialogButton;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Layout;
public partial class DeviceLogicalLayoutDialogViewModel : ContentDialogViewModelBase
{
@@ -24,7 +24,7 @@ public partial class DeviceLogicalLayoutDialogViewModel : ContentDialogViewModel
public DeviceLogicalLayoutDialogViewModel(ArtemisDevice device)
{
Device = device;
ApplyLogicalLayout = ReactiveCommand.Create(ExecuteApplyLogicalLayout, this.WhenAnyValue(vm => vm.SelectedRegion).Select(r => r != null));
ApplyLogicalLayout = ReactiveCommand.Create(ExecuteApplyLogicalLayout, this.WhenAnyValue<DeviceLogicalLayoutDialogViewModel, RegionInfo>(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 &&
@@ -3,9 +3,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
xmlns:layout="clr-namespace:Artemis.UI.Screens.Device.Layout"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Device.DevicePhysicalLayoutDialogView"
x:DataType="device:DevicePhysicalLayoutDialogViewModel">
x:Class="Artemis.UI.Screens.Device.Layout.DevicePhysicalLayoutDialogView"
x:DataType="layout:DevicePhysicalLayoutDialogViewModel">
<Grid RowDefinitions="Auto,*">
<StackPanel Grid.Row="0">
<StackPanel Orientation="Horizontal">
@@ -1,7 +1,6 @@
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Layout;
public partial class DevicePhysicalLayoutDialogView : ReactiveUserControl<DevicePhysicalLayoutDialogViewModel>
{
@@ -7,7 +7,7 @@ using Artemis.UI.Shared.Services;
using FluentAvalonia.UI.Controls;
using ReactiveUI;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Layout;
public class DevicePhysicalLayoutDialogViewModel : ContentDialogViewModelBase
{
@@ -0,0 +1,25 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
xmlns:layoutProviders="clr-namespace:Artemis.UI.Screens.Device.Layout.LayoutProviders"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Device.Layout.LayoutProviders.CustomLayoutView"
x:DataType="layoutProviders:CustomLayoutViewModel"
ClipToBounds="False">
<StackPanel ClipToBounds="False">
<Border Classes="card-separator" />
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
<StackPanel Grid.Row="1" Grid.Column="0">
<TextBlock Text="Custom layout path" />
<TextBlock Classes="subtitle" FontSize="12" Text="{CompiledBinding Device.LayoutSelection.Parameter, TargetNullValue=None}" TextWrapping="Wrap" />
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
<Button Content="Clear" Command="{CompiledBinding ClearCustomLayout}" IsEnabled="{CompiledBinding !!Device.LayoutSelection.Parameter}" />
<!-- 5 pixels of margin between the buttons -->
<Button Margin="5,0,0,0" Content="Browse" Command="{CompiledBinding BrowseCustomLayout}" />
</StackPanel>
</Grid>
</StackPanel>
</UserControl>
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public partial class CustomLayoutView : UserControl
{
public CustomLayoutView()
{
InitializeComponent();
}
}
@@ -0,0 +1,71 @@
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Providers;
using Artemis.Core.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public class CustomLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
{
private readonly CustomPathLayoutProvider _layoutProvider;
private readonly IDeviceService _deviceService;
public CustomLayoutViewModel(IWindowService windowService, INotificationService notificationService, CustomPathLayoutProvider layoutProvider, IDeviceService deviceService)
{
_layoutProvider = layoutProvider;
_deviceService = deviceService;
_windowService = windowService;
_notificationService = notificationService;
}
/// <inheritdoc />
public string Name => "Custom";
/// <inheritdoc />
public string Description => "Select a layout file from a folder on your computer";
/// <inheritdoc />
public bool IsMatch(ArtemisDevice device)
{
return _layoutProvider.IsMatch(device);
}
public ArtemisDevice Device { get; set; } = null!;
private readonly IWindowService _windowService;
private readonly INotificationService _notificationService;
public void ClearCustomLayout()
{
Device.LayoutSelection.Type = CustomPathLayoutProvider.LayoutType;
Device.LayoutSelection.Parameter = null;
_notificationService.CreateNotification()
.WithMessage("Cleared imported layout.")
.WithSeverity(NotificationSeverity.Informational);
_deviceService.SaveDevice(Device);
}
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)
{
Device.LayoutSelection.Type = CustomPathLayoutProvider.LayoutType;
Device.LayoutSelection.Parameter = files[0];
_notificationService.CreateNotification()
.WithTitle("Imported layout")
.WithMessage($"File loaded from {files[0]}")
.WithSeverity(NotificationSeverity.Informational);
}
_deviceService.SaveDevice(Device);
}
}
@@ -0,0 +1,10 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Device.Layout.LayoutProviders.DefaultLayoutView">
<TextBlock Classes="subtitle" FontSize="12">
Loading the default layout from the plugin or User Layouts folder.
</TextBlock>
</UserControl>
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public partial class DefaultLayoutView : UserControl
{
public DefaultLayoutView()
{
InitializeComponent();
}
}
@@ -0,0 +1,29 @@
using Artemis.Core;
using Artemis.Core.Providers;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public class DefaultLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
{
private readonly DefaultLayoutProvider _layoutProvider;
public DefaultLayoutViewModel(DefaultLayoutProvider layoutProvider)
{
_layoutProvider = layoutProvider;
}
public ArtemisDevice Device { get; set; } = null!;
/// <inheritdoc />
public string Name => "Default";
/// <inheritdoc />
public string Description => "Attempts to load a layout from the default paths";
/// <inheritdoc />
public bool IsMatch(ArtemisDevice device)
{
return _layoutProvider.IsMatch(device);
}
}
@@ -0,0 +1,14 @@
using Artemis.Core;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public interface ILayoutProviderViewModel
{
string Name { get; }
string Description { get; }
bool IsMatch(ArtemisDevice device);
ArtemisDevice Device { get; set; }
}
@@ -0,0 +1,10 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Device.Layout.LayoutProviders.NoneLayoutView">
<TextBlock Classes="subtitle" FontSize="12">
Not loading any layout, leaving LEDs to be positioned by the device provider.
</TextBlock>
</UserControl>
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public partial class NoneLayoutView : UserControl
{
public NoneLayoutView()
{
InitializeComponent();
}
}
@@ -0,0 +1,29 @@
using Artemis.Core;
using Artemis.Core.Providers;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public class NoneLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
{
private readonly NoneLayoutProvider _layoutProvider;
public NoneLayoutViewModel(NoneLayoutProvider layoutProvider)
{
_layoutProvider = layoutProvider;
}
public ArtemisDevice Device { get; set; } = null!;
/// <inheritdoc />
public string Name => "None";
/// <inheritdoc />
public string Description => "Do not load any layout";
/// <inheritdoc />
public bool IsMatch(ArtemisDevice device)
{
return _layoutProvider.IsMatch(device);
}
}
@@ -0,0 +1,11 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Device.Layout.LayoutProviders.WorkshopLayoutView">
<TextBlock Classes="subtitle" FontSize="12">
Here you'll do workshop things
</TextBlock>
</UserControl>
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public partial class WorkshopLayoutView : UserControl
{
public WorkshopLayoutView()
{
InitializeComponent();
}
}
@@ -0,0 +1,29 @@
using Artemis.Core;
using Artemis.UI.Shared;
using Artemis.WebClient.Workshop.Providers;
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
public class WorkshopLayoutViewModel : ViewModelBase, ILayoutProviderViewModel
{
private readonly WorkshopLayoutProvider _layoutProvider;
public WorkshopLayoutViewModel(WorkshopLayoutProvider layoutProvider)
{
_layoutProvider = layoutProvider;
}
public ArtemisDevice Device { get; set; } = null!;
/// <inheritdoc />
public string Name => "Workshop";
/// <inheritdoc />
public string Description => "Load a layout from the workshop";
/// <inheritdoc />
public bool IsMatch(ArtemisDevice device)
{
return _layoutProvider.IsMatch(device);
}
}
@@ -2,7 +2,7 @@
using Artemis.Core;
using Artemis.UI.Shared;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Leds;
public class DeviceLedsTabLedViewModel : ViewModelBase
{
@@ -5,9 +5,10 @@
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:shared="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
xmlns:leds="clr-namespace:Artemis.UI.Screens.Device.Leds"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Device.DeviceLedsTabView"
x:DataType="device:DeviceLedsTabViewModel">
x:Class="Artemis.UI.Screens.Device.Leds.DeviceLedsTabView"
x:DataType="leds:DeviceLedsTabViewModel">
<UserControl.Resources>
<converters:UriToFileNameConverter x:Key="UriToFileNameConverter" />
<converters:LedIdToStringConverter x:Key="LedIdToStringConverter" />
@@ -1,7 +1,6 @@
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Leds;
public partial class DeviceLedsTabView : ReactiveUserControl<DeviceLedsTabViewModel>
{
@@ -8,7 +8,7 @@ using Artemis.UI.Shared;
using DynamicData.Binding;
using ReactiveUI;
namespace Artemis.UI.Screens.Device;
namespace Artemis.UI.Screens.Device.Leds;
public class DeviceLedsTabViewModel : ActivatableViewModelBase
{
@@ -46,7 +46,7 @@ public partial class InstalledTabItemViewModel : ViewModelBase
private async Task ExecuteViewLocal(CancellationToken cancellationToken)
{
if (InstalledEntry.EntryType == EntryType.Profile && Guid.TryParse(InstalledEntry.LocalReference, out Guid profileId))
if (InstalledEntry.EntryType == EntryType.Profile && InstalledEntry.TryGetMetadata("ProfileId", out Guid profileId))
{
await _router.Navigate($"profile-editor/{profileId}");
}
@@ -63,7 +63,7 @@ public partial class LayoutSelectionStepViewModel : SubmissionViewModel
try
{
ArtemisLayout layout = new(selected[0], LayoutSource.User);
ArtemisLayout layout = new(selected[0]);
if (!layout.IsValid)
{
await _windowService.ShowConfirmContentDialog("Failed to load layout", "The selected file does not appear to be a valid RGB.NET layout file.", "Close", null);