mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Devices - Reworking layout loading
This commit is contained in:
parent
9393bf2b68
commit
e8590abd61
@ -63,6 +63,11 @@ public static class Constants
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string LayoutsFolder = Path.Combine(DataFolder, "User Layouts");
|
public static readonly string LayoutsFolder = Path.Combine(DataFolder, "User Layouts");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The full path to the Artemis user layouts folder
|
||||||
|
/// </summary>
|
||||||
|
public static readonly string WorkshopFolder = Path.Combine(DataFolder, "workshop");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current API version for plugins
|
/// The current API version for plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -155,4 +160,5 @@ public static class Constants
|
|||||||
/// Gets the graphics context to be used for rendering by SkiaSharp.
|
/// Gets the graphics context to be used for rendering by SkiaSharp.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IManagedGraphicsContext? ManagedGraphicsContext { get; internal set; }
|
public static IManagedGraphicsContext? ManagedGraphicsContext { get; internal set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Artemis.Core.DryIoc.Factories;
|
using Artemis.Core.DryIoc.Factories;
|
||||||
|
using Artemis.Core.Providers;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.Storage;
|
using Artemis.Storage;
|
||||||
using Artemis.Storage.Migrations.Interfaces;
|
using Artemis.Storage.Migrations.Interfaces;
|
||||||
@ -36,6 +37,7 @@ public static class ContainerExtensions
|
|||||||
// Bind migrations
|
// Bind migrations
|
||||||
container.RegisterMany(storageAssembly, type => type.IsAssignableTo<IStorageMigration>(), Reuse.Singleton, nonPublicServiceTypes: true);
|
container.RegisterMany(storageAssembly, type => type.IsAssignableTo<IStorageMigration>(), Reuse.Singleton, nonPublicServiceTypes: true);
|
||||||
|
|
||||||
|
container.RegisterMany(coreAssembly, type => type.IsAssignableTo<ILayoutProvider>(), Reuse.Singleton);
|
||||||
container.Register<IPluginSettingsFactory, PluginSettingsFactory>(Reuse.Singleton);
|
container.Register<IPluginSettingsFactory, PluginSettingsFactory>(Reuse.Singleton);
|
||||||
container.Register(Made.Of(_ => ServiceInfo.Of<IPluginSettingsFactory>(), f => f.CreatePluginSettings(Arg.Index<Type>(0)), r => r.Parent.ImplementationType));
|
container.Register(Made.Of(_ => ServiceInfo.Of<IPluginSettingsFactory>(), f => f.CreatePluginSettings(Arg.Index<Type>(0)), r => r.Parent.ImplementationType));
|
||||||
container.Register<ILoggerFactory, LoggerFactory>(Reuse.Singleton);
|
container.Register<ILoggerFactory, LoggerFactory>(Reuse.Singleton);
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.DeviceProviders;
|
using Artemis.Core.DeviceProviders;
|
||||||
|
using Artemis.Core.Providers;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.Storage.Entities.Surface;
|
using Artemis.Storage.Entities.Surface;
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
@ -46,6 +46,7 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
|
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
|
||||||
InputMappings = new Dictionary<ArtemisLed, ArtemisLed>();
|
InputMappings = new Dictionary<ArtemisLed, ArtemisLed>();
|
||||||
Categories = new HashSet<DeviceCategory>();
|
Categories = new HashSet<DeviceCategory>();
|
||||||
|
LayoutSelection = new LayoutSelection {Type = DefaultLayoutProvider.LayoutType};
|
||||||
|
|
||||||
RgbDevice.ColorCorrections.Clear();
|
RgbDevice.ColorCorrections.Clear();
|
||||||
RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this));
|
RgbDevice.ColorCorrections.Add(new ScaleColorCorrection(this));
|
||||||
@ -74,6 +75,7 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
|
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
|
||||||
InputMappings = new Dictionary<ArtemisLed, ArtemisLed>();
|
InputMappings = new Dictionary<ArtemisLed, ArtemisLed>();
|
||||||
Categories = new HashSet<DeviceCategory>();
|
Categories = new HashSet<DeviceCategory>();
|
||||||
|
LayoutSelection = new LayoutSelection {Type = DefaultLayoutProvider.LayoutType};
|
||||||
|
|
||||||
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
|
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
|
||||||
InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier));
|
InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier));
|
||||||
@ -153,6 +155,8 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public HashSet<DeviceCategory> Categories { get; }
|
public HashSet<DeviceCategory> Categories { get; }
|
||||||
|
|
||||||
|
public LayoutSelection LayoutSelection { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the X-position of the device
|
/// Gets or sets the X-position of the device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -293,19 +297,6 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a boolean indicating whether falling back to default layouts is enabled or not
|
|
||||||
/// </summary>
|
|
||||||
public bool DisableDefaultLayout
|
|
||||||
{
|
|
||||||
get => DeviceEntity.DisableDefaultLayout;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
DeviceEntity.DisableDefaultLayout = value;
|
|
||||||
OnPropertyChanged(nameof(DisableDefaultLayout));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the logical layout of the device e.g. DE, UK or US.
|
/// Gets or sets the logical layout of the device e.g. DE, UK or US.
|
||||||
/// <para>Only applicable to keyboards</para>
|
/// <para>Only applicable to keyboards</para>
|
||||||
@ -320,20 +311,6 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the path of the custom layout to load when calling <see cref="GetBestDeviceLayout" />
|
|
||||||
/// for this device
|
|
||||||
/// </summary>
|
|
||||||
public string? CustomLayoutPath
|
|
||||||
{
|
|
||||||
get => DeviceEntity.CustomLayoutPath;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
DeviceEntity.CustomLayoutPath = value;
|
|
||||||
OnPropertyChanged(nameof(CustomLayoutPath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the layout of the device expanded with Artemis-specific data
|
/// Gets the layout of the device expanded with Artemis-specific data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -381,40 +358,6 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
return artemisLed;
|
return artemisLed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the most preferred device layout for this device.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>The most preferred device layout for this device.</returns>
|
|
||||||
public ArtemisLayout? GetBestDeviceLayout()
|
|
||||||
{
|
|
||||||
ArtemisLayout? layout;
|
|
||||||
|
|
||||||
// Configured layout path takes precedence over all other options
|
|
||||||
if (CustomLayoutPath != null)
|
|
||||||
{
|
|
||||||
layout = new ArtemisLayout(CustomLayoutPath, LayoutSource.Configured);
|
|
||||||
if (layout.IsValid)
|
|
||||||
return layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for a layout provided by the user
|
|
||||||
layout = DeviceProvider.LoadUserLayout(this);
|
|
||||||
if (layout.IsValid)
|
|
||||||
return layout;
|
|
||||||
|
|
||||||
if (DisableDefaultLayout)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// Look for a layout provided by the plugin
|
|
||||||
layout = DeviceProvider.LoadLayout(this);
|
|
||||||
if (layout.IsValid)
|
|
||||||
return layout;
|
|
||||||
|
|
||||||
// Finally fall back to a default layout
|
|
||||||
layout = ArtemisLayout.GetDefaultLayout(this);
|
|
||||||
return layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when the underlying RGB.NET device was updated
|
/// Occurs when the underlying RGB.NET device was updated
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -534,6 +477,9 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
DeviceEntity.Categories.Clear();
|
DeviceEntity.Categories.Clear();
|
||||||
foreach (DeviceCategory deviceCategory in Categories)
|
foreach (DeviceCategory deviceCategory in Categories)
|
||||||
DeviceEntity.Categories.Add((int) deviceCategory);
|
DeviceEntity.Categories.Add((int) deviceCategory);
|
||||||
|
|
||||||
|
DeviceEntity.LayoutType = LayoutSelection.Type;
|
||||||
|
DeviceEntity.LayoutParameter = LayoutSelection.Parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Load()
|
internal void Load()
|
||||||
@ -548,6 +494,9 @@ public class ArtemisDevice : CorePropertyChanged
|
|||||||
if (!Categories.Any())
|
if (!Categories.Any())
|
||||||
ApplyDefaultCategories();
|
ApplyDefaultCategories();
|
||||||
|
|
||||||
|
LayoutSelection.Type = DeviceEntity.LayoutType;
|
||||||
|
LayoutSelection.Parameter = DeviceEntity.LayoutParameter;
|
||||||
|
|
||||||
LoadInputMappings();
|
LoadInputMappings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,16 +12,17 @@ namespace Artemis.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ArtemisLayout
|
public class ArtemisLayout
|
||||||
{
|
{
|
||||||
|
private static readonly string DefaultLayoutPath = Path.Combine(Constants.ApplicationFolder, "DefaultLayouts", "Artemis");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="ArtemisLayout" /> class
|
/// Creates a new instance of the <see cref="ArtemisLayout" /> class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filePath">The path of the layout XML file</param>
|
/// <param name="filePath">The path of the layout XML file</param>
|
||||||
/// <param name="source">The source from where this layout is being loaded</param>
|
public ArtemisLayout(string filePath)
|
||||||
public ArtemisLayout(string filePath, LayoutSource source)
|
|
||||||
{
|
{
|
||||||
FilePath = filePath;
|
FilePath = filePath;
|
||||||
Source = source;
|
|
||||||
Leds = new List<ArtemisLedLayout>();
|
Leds = new List<ArtemisLedLayout>();
|
||||||
|
IsDefaultLayout = filePath.StartsWith(DefaultLayoutPath);
|
||||||
|
|
||||||
LoadLayout();
|
LoadLayout();
|
||||||
}
|
}
|
||||||
@ -31,11 +32,6 @@ public class ArtemisLayout
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string FilePath { get; }
|
public string FilePath { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the source from where this layout was loaded
|
|
||||||
/// </summary>
|
|
||||||
public LayoutSource Source { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a boolean indicating whether a valid layout was loaded
|
/// Gets a boolean indicating whether a valid layout was loaded
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -61,6 +57,8 @@ public class ArtemisLayout
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public LayoutCustomDeviceData LayoutCustomDeviceData { get; private set; } = null!;
|
public LayoutCustomDeviceData LayoutCustomDeviceData { get; private set; } = null!;
|
||||||
|
|
||||||
|
public bool IsDefaultLayout { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies the layout to the provided device
|
/// Applies the layout to the provided device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -121,29 +119,28 @@ public class ArtemisLayout
|
|||||||
|
|
||||||
internal static ArtemisLayout? GetDefaultLayout(ArtemisDevice device)
|
internal static ArtemisLayout? GetDefaultLayout(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
string layoutFolder = Path.Combine(Constants.ApplicationFolder, "DefaultLayouts", "Artemis");
|
|
||||||
if (device.DeviceType == RGBDeviceType.Keyboard)
|
if (device.DeviceType == RGBDeviceType.Keyboard)
|
||||||
{
|
{
|
||||||
// XL layout is defined by its programmable macro keys
|
// XL layout is defined by its programmable macro keys
|
||||||
if (device.Leds.Any(l => l.RgbLed.Id >= LedId.Keyboard_Programmable1 && l.RgbLed.Id <= LedId.Keyboard_Programmable32))
|
if (device.Leds.Any(l => l.RgbLed.Id >= LedId.Keyboard_Programmable1 && l.RgbLed.Id <= LedId.Keyboard_Programmable32))
|
||||||
{
|
{
|
||||||
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder, "Keyboard", "Artemis XL keyboard-ANSI.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Keyboard", "Artemis XL keyboard-ANSI.xml"));
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder, "Keyboard", "Artemis XL keyboard-ISO.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Keyboard", "Artemis XL keyboard-ISO.xml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// L layout is defined by its numpad
|
// L layout is defined by its numpad
|
||||||
if (device.Leds.Any(l => l.RgbLed.Id >= LedId.Keyboard_NumLock && l.RgbLed.Id <= LedId.Keyboard_NumPeriodAndDelete))
|
if (device.Leds.Any(l => l.RgbLed.Id >= LedId.Keyboard_NumLock && l.RgbLed.Id <= LedId.Keyboard_NumPeriodAndDelete))
|
||||||
{
|
{
|
||||||
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder + "Keyboard", "Artemis L keyboard-ANSI.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Keyboard", "Artemis L keyboard-ANSI.xml"));
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder + "Keyboard", "Artemis L keyboard-ISO.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Keyboard", "Artemis L keyboard-ISO.xml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// No numpad will result in TKL
|
// No numpad will result in TKL
|
||||||
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
if (device.PhysicalLayout == KeyboardLayoutType.ANSI)
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder + "Keyboard", "Artemis TKL keyboard-ANSI.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Keyboard", "Artemis TKL keyboard-ANSI.xml"));
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder + "Keyboard", "Artemis TKL keyboard-ISO.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Keyboard", "Artemis TKL keyboard-ISO.xml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (device.DeviceType == RGBDeviceType.Mouse)
|
// if (device.DeviceType == RGBDeviceType.Mouse)
|
||||||
@ -151,21 +148,21 @@ public class ArtemisLayout
|
|||||||
// if (device.Leds.Count == 1)
|
// if (device.Leds.Count == 1)
|
||||||
// {
|
// {
|
||||||
// if (device.Leds.Any(l => l.RgbLed.Id == LedId.Logo))
|
// if (device.Leds.Any(l => l.RgbLed.Id == LedId.Logo))
|
||||||
// return new ArtemisLayout(Path.Combine(layoutFolder + "Mouse", "1 LED mouse logo.xml"), LayoutSource.Default);
|
// return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Mouse", "1 LED mouse logo.xml"), LayoutSource.Default);
|
||||||
// return new ArtemisLayout(Path.Combine(layoutFolder + "Mouse", "1 LED mouse.xml"), LayoutSource.Default);
|
// return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Mouse", "1 LED mouse.xml"), LayoutSource.Default);
|
||||||
// }
|
// }
|
||||||
// if (device.Leds.Any(l => l.RgbLed.Id == LedId.Logo))
|
// if (device.Leds.Any(l => l.RgbLed.Id == LedId.Logo))
|
||||||
// return new ArtemisLayout(Path.Combine(layoutFolder + "Mouse", "4 LED mouse logo.xml"), LayoutSource.Default);
|
// return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Mouse", "4 LED mouse logo.xml"), LayoutSource.Default);
|
||||||
// return new ArtemisLayout(Path.Combine(layoutFolder + "Mouse", "4 LED mouse.xml"), LayoutSource.Default);
|
// return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Mouse", "4 LED mouse.xml"), LayoutSource.Default);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (device.DeviceType == RGBDeviceType.Headset)
|
if (device.DeviceType == RGBDeviceType.Headset)
|
||||||
{
|
{
|
||||||
if (device.Leds.Count == 1)
|
if (device.Leds.Count == 1)
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder + "Headset", "Artemis 1 LED headset.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Headset", "Artemis 1 LED headset.xml"));
|
||||||
if (device.Leds.Count == 2)
|
if (device.Leds.Count == 2)
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder + "Headset", "Artemis 2 LED headset.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Headset", "Artemis 2 LED headset.xml"));
|
||||||
return new ArtemisLayout(Path.Combine(layoutFolder + "Headset", "Artemis 4 LED headset.xml"), LayoutSource.Default);
|
return new ArtemisLayout(Path.Combine(DefaultLayoutPath, "Headset", "Artemis 4 LED headset.xml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -206,30 +203,10 @@ public class ArtemisLayout
|
|||||||
else
|
else
|
||||||
Image = null;
|
Image = null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// <inheritdoc />
|
||||||
/// <summary>
|
public override string ToString()
|
||||||
/// Represents a source from where a layout came
|
{
|
||||||
/// </summary>
|
return FilePath;
|
||||||
public enum LayoutSource
|
}
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A layout loaded from config
|
|
||||||
/// </summary>
|
|
||||||
Configured,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A layout loaded from the user layout folder
|
|
||||||
/// </summary>
|
|
||||||
User,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A layout loaded from the plugin folder
|
|
||||||
/// </summary>
|
|
||||||
Plugin,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A default layout loaded as a fallback option
|
|
||||||
/// </summary>
|
|
||||||
Default
|
|
||||||
}
|
}
|
||||||
28
src/Artemis.Core/Models/Surface/LayoutSelection.cs
Normal file
28
src/Artemis.Core/Models/Surface/LayoutSelection.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
namespace Artemis.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a reference to a layout for a device.
|
||||||
|
/// </summary>
|
||||||
|
public class LayoutSelection : CorePropertyChanged
|
||||||
|
{
|
||||||
|
private string? _type;
|
||||||
|
private string? _parameter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets what kind of layout reference this is.
|
||||||
|
/// </summary>
|
||||||
|
public string? Type
|
||||||
|
{
|
||||||
|
get => _type;
|
||||||
|
set => SetAndNotify(ref _type, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the parameter of the layout reference, such as a file path of workshop entry ID.
|
||||||
|
/// </summary>
|
||||||
|
public string? Parameter
|
||||||
|
{
|
||||||
|
get => _parameter;
|
||||||
|
set => SetAndNotify(ref _parameter, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -62,7 +62,7 @@ public abstract class DeviceProvider : PluginFeature
|
|||||||
device.DeviceType.ToString(),
|
device.DeviceType.ToString(),
|
||||||
GetDeviceLayoutName(device)
|
GetDeviceLayoutName(device)
|
||||||
);
|
);
|
||||||
return new ArtemisLayout(filePath, LayoutSource.Plugin);
|
return new ArtemisLayout(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -79,7 +79,7 @@ public abstract class DeviceProvider : PluginFeature
|
|||||||
device.DeviceType.ToString(),
|
device.DeviceType.ToString(),
|
||||||
GetDeviceLayoutName(device)
|
GetDeviceLayoutName(device)
|
||||||
);
|
);
|
||||||
return new ArtemisLayout(filePath, LayoutSource.User);
|
return new ArtemisLayout(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
28
src/Artemis.Core/Providers/CustomPathLayoutProvider.cs
Normal file
28
src/Artemis.Core/Providers/CustomPathLayoutProvider.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using RGB.NET.Layout;
|
||||||
|
|
||||||
|
namespace Artemis.Core.Providers;
|
||||||
|
|
||||||
|
public class CustomPathLayoutProvider : ILayoutProvider
|
||||||
|
{
|
||||||
|
public static string LayoutType = "CustomPath";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
if (device.LayoutSelection.Parameter == null)
|
||||||
|
return null;
|
||||||
|
return new ArtemisLayout(device.LayoutSelection.Parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ApplyLayout(ArtemisDevice device, ArtemisLayout layout)
|
||||||
|
{
|
||||||
|
device.ApplyLayout(layout, device.DeviceProvider.CreateMissingLedsSupported, device.DeviceProvider.RemoveExcessiveLedsSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsMatch(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
return device.LayoutSelection.Type == LayoutType;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/Artemis.Core/Providers/DefaultLayoutProvider.cs
Normal file
31
src/Artemis.Core/Providers/DefaultLayoutProvider.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
namespace Artemis.Core.Providers;
|
||||||
|
|
||||||
|
public class DefaultLayoutProvider : ILayoutProvider
|
||||||
|
{
|
||||||
|
public static string LayoutType = "Default";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
// Look for a layout provided by the plugin
|
||||||
|
ArtemisLayout layout = device.DeviceProvider.LoadLayout(device);
|
||||||
|
|
||||||
|
// Finally fall back to a default layout
|
||||||
|
return layout.IsValid ? layout : ArtemisLayout.GetDefaultLayout(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ApplyLayout(ArtemisDevice device, ArtemisLayout layout)
|
||||||
|
{
|
||||||
|
if (layout.IsDefaultLayout)
|
||||||
|
device.ApplyLayout(layout, false, false);
|
||||||
|
else
|
||||||
|
device.ApplyLayout(layout, device.DeviceProvider.CreateMissingLedsSupported, device.DeviceProvider.RemoveExcessiveLedsSupported);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsMatch(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
return device.LayoutSelection.Type == LayoutType;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/Artemis.Core/Providers/Interfaces/ILayoutProvider.cs
Normal file
17
src/Artemis.Core/Providers/Interfaces/ILayoutProvider.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace Artemis.Core.Providers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a class that can provide Artemis layouts for devices.
|
||||||
|
/// </summary>
|
||||||
|
public interface ILayoutProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// If available, loads an Artemis layout for the provided device.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="device">The device to load the layout for.</param>
|
||||||
|
/// <returns>The resulting layout if one was available; otherwise <see langword="null"/>.</returns>
|
||||||
|
ArtemisLayout? GetDeviceLayout(ArtemisDevice device);
|
||||||
|
|
||||||
|
void ApplyLayout(ArtemisDevice device, ArtemisLayout layout);
|
||||||
|
bool IsMatch(ArtemisDevice device);
|
||||||
|
}
|
||||||
24
src/Artemis.Core/Providers/NoneLayoutProvider.cs
Normal file
24
src/Artemis.Core/Providers/NoneLayoutProvider.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
namespace Artemis.Core.Providers;
|
||||||
|
|
||||||
|
public class NoneLayoutProvider : ILayoutProvider
|
||||||
|
{
|
||||||
|
public static string LayoutType = "None";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ApplyLayout(ArtemisDevice device, ArtemisLayout layout)
|
||||||
|
{
|
||||||
|
device.ApplyLayout(null, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsMatch(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
return device.LayoutSelection.Type == LayoutType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.DeviceProviders;
|
using Artemis.Core.DeviceProviders;
|
||||||
|
using Artemis.Core.Providers;
|
||||||
using Artemis.Core.Services.Models;
|
using Artemis.Core.Services.Models;
|
||||||
using Artemis.Storage.Entities.Surface;
|
using Artemis.Storage.Entities.Surface;
|
||||||
using Artemis.Storage.Repositories.Interfaces;
|
using Artemis.Storage.Repositories.Interfaces;
|
||||||
@ -18,15 +19,21 @@ internal class DeviceService : IDeviceService
|
|||||||
private readonly IPluginManagementService _pluginManagementService;
|
private readonly IPluginManagementService _pluginManagementService;
|
||||||
private readonly IDeviceRepository _deviceRepository;
|
private readonly IDeviceRepository _deviceRepository;
|
||||||
private readonly Lazy<IRenderService> _renderService;
|
private readonly Lazy<IRenderService> _renderService;
|
||||||
|
private readonly Func<IEnumerable<ILayoutProvider>> _getLayoutProviders;
|
||||||
private readonly List<ArtemisDevice> _enabledDevices = new();
|
private readonly List<ArtemisDevice> _enabledDevices = new();
|
||||||
private readonly List<ArtemisDevice> _devices = new();
|
private readonly List<ArtemisDevice> _devices = new();
|
||||||
|
|
||||||
public DeviceService(ILogger logger, IPluginManagementService pluginManagementService, IDeviceRepository deviceRepository, Lazy<IRenderService> renderService)
|
public DeviceService(ILogger logger,
|
||||||
|
IPluginManagementService pluginManagementService,
|
||||||
|
IDeviceRepository deviceRepository,
|
||||||
|
Lazy<IRenderService> renderService,
|
||||||
|
Func<IEnumerable<ILayoutProvider>> getLayoutProviders)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_pluginManagementService = pluginManagementService;
|
_pluginManagementService = pluginManagementService;
|
||||||
_deviceRepository = deviceRepository;
|
_deviceRepository = deviceRepository;
|
||||||
_renderService = renderService;
|
_renderService = renderService;
|
||||||
|
_getLayoutProviders = getLayoutProviders;
|
||||||
|
|
||||||
EnabledDevices = new ReadOnlyCollection<ArtemisDevice>(_enabledDevices);
|
EnabledDevices = new ReadOnlyCollection<ArtemisDevice>(_enabledDevices);
|
||||||
Devices = new ReadOnlyCollection<ArtemisDevice>(_devices);
|
Devices = new ReadOnlyCollection<ArtemisDevice>(_devices);
|
||||||
@ -157,12 +164,23 @@ internal class DeviceService : IDeviceService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ApplyDeviceLayout(ArtemisDevice device, ArtemisLayout? layout)
|
public void LoadDeviceLayout(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
if (layout == null || layout.Source == LayoutSource.Default)
|
ILayoutProvider? provider = _getLayoutProviders().FirstOrDefault(p => p.IsMatch(device));
|
||||||
device.ApplyLayout(layout, false, false);
|
if (provider == null)
|
||||||
|
_logger.Warning("Could not find a layout provider for type {LayoutType} of device {Device}", device.LayoutSelection.Type, device);
|
||||||
|
|
||||||
|
ArtemisLayout? layout = provider?.GetDeviceLayout(device);
|
||||||
|
if (layout != null && !layout.IsValid)
|
||||||
|
{
|
||||||
|
_logger.Warning("Got an invalid layout {Layout} from {LayoutProvider}", layout, provider!.GetType().FullName);
|
||||||
|
layout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout == null)
|
||||||
|
device.ApplyLayout(null, false, false);
|
||||||
else
|
else
|
||||||
device.ApplyLayout(layout, device.DeviceProvider.CreateMissingLedsSupported, device.DeviceProvider.RemoveExcessiveLedsSupported);
|
provider!.ApplyLayout(device, layout);
|
||||||
|
|
||||||
UpdateLeds();
|
UpdateLeds();
|
||||||
}
|
}
|
||||||
@ -230,7 +248,7 @@ internal class DeviceService : IDeviceService
|
|||||||
device = new ArtemisDevice(rgbDevice, deviceProvider);
|
device = new ArtemisDevice(rgbDevice, deviceProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplyDeviceLayout(device, device.GetBestDeviceLayout());
|
LoadDeviceLayout(device);
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,11 +43,10 @@ public interface IDeviceService : IArtemisService
|
|||||||
void AutoArrangeDevices();
|
void AutoArrangeDevices();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apples the provided <see cref="ArtemisLayout" /> to the provided <see cref="ArtemisDevice" />
|
/// Apples the best available to the provided <see cref="ArtemisDevice" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="device"></param>
|
/// <param name="device"></param>
|
||||||
/// <param name="layout"></param>
|
void LoadDeviceLayout(ArtemisDevice device);
|
||||||
void ApplyDeviceLayout(ArtemisDevice device, ArtemisLayout? layout);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables the provided device
|
/// Enables the provided device
|
||||||
|
|||||||
@ -23,10 +23,10 @@ public class DeviceEntity
|
|||||||
public float BlueScale { get; set; }
|
public float BlueScale { get; set; }
|
||||||
public bool IsEnabled { get; set; }
|
public bool IsEnabled { get; set; }
|
||||||
|
|
||||||
public bool DisableDefaultLayout { get; set; }
|
|
||||||
public int PhysicalLayout { get; set; }
|
public int PhysicalLayout { get; set; }
|
||||||
public string LogicalLayout { get; set; }
|
public string LogicalLayout { get; set; }
|
||||||
public string CustomLayoutPath { get; set; }
|
public string LayoutType { get; set; }
|
||||||
|
public string LayoutParameter { get; set; }
|
||||||
|
|
||||||
public List<DeviceInputIdentifierEntity> InputIdentifiers { get; set; }
|
public List<DeviceInputIdentifierEntity> InputIdentifiers { get; set; }
|
||||||
public List<InputMappingEntity> InputMappings { get; set; }
|
public List<InputMappingEntity> InputMappings { get; set; }
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Artemis.Storage.Entities.Workshop;
|
namespace Artemis.Storage.Entities.Workshop;
|
||||||
|
|
||||||
@ -17,5 +18,5 @@ public class EntryEntity
|
|||||||
public string ReleaseVersion { get; set; }
|
public string ReleaseVersion { get; set; }
|
||||||
public DateTimeOffset InstalledAt { get; set; }
|
public DateTimeOffset InstalledAt { get; set; }
|
||||||
|
|
||||||
public string LocalReference { get; set; }
|
public Dictionary<string,object> Metadata { get; set; }
|
||||||
}
|
}
|
||||||
@ -58,19 +58,4 @@
|
|||||||
<HintPath>..\..\..\RGB.NET\bin\net7.0\RGB.NET.Layout.dll</HintPath>
|
<HintPath>..\..\..\RGB.NET\bin\net7.0\RGB.NET.Layout.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Screens\Workshop\Entries\List\EntryListInputView.axaml.cs">
|
|
||||||
<DependentUpon>EntryListInputView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Workshop\Entries\List\EntryListItemView.axaml.cs">
|
|
||||||
<DependentUpon>EntryListItemView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Workshop\Entries\Details\EntrySpecificationsView.axaml.cs">
|
|
||||||
<DependentUpon>EntrySpecificationsView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Artemis.UI.DryIoc.Factories;
|
using Artemis.UI.DryIoc.Factories;
|
||||||
using Artemis.UI.DryIoc.InstanceProviders;
|
using Artemis.UI.DryIoc.InstanceProviders;
|
||||||
|
using Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
||||||
using Artemis.UI.Screens.VisualScripting;
|
using Artemis.UI.Screens.VisualScripting;
|
||||||
using Artemis.UI.Services.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
using Artemis.UI.Services.Updating;
|
using Artemis.UI.Services.Updating;
|
||||||
@ -26,6 +27,7 @@ public static class ContainerExtensions
|
|||||||
|
|
||||||
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<ViewModelBase>(), setup: Setup.With(preventDisposal: true));
|
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<ViewModelBase>(), setup: Setup.With(preventDisposal: true));
|
||||||
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IToolViewModel>() && type.IsInterface, setup: Setup.With(preventDisposal: true));
|
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IToolViewModel>() && type.IsInterface, setup: Setup.With(preventDisposal: true));
|
||||||
|
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<ILayoutProviderViewModel>() && type.IsInterface, setup: Setup.With(preventDisposal: true));
|
||||||
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IVmFactory>() && type != typeof(PropertyVmFactory));
|
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IVmFactory>() && type != typeof(PropertyVmFactory));
|
||||||
|
|
||||||
container.Register<NodeScriptWindowViewModelBase, NodeScriptWindowViewModel>(Reuse.Singleton);
|
container.Register<NodeScriptWindowViewModelBase, NodeScriptWindowViewModel>(Reuse.Singleton);
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
using System;
|
using System.Collections.ObjectModel;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.LayerBrushes;
|
using Artemis.Core.LayerBrushes;
|
||||||
using Artemis.Core.LayerEffects;
|
using Artemis.Core.LayerEffects;
|
||||||
using Artemis.Core.ScriptingProviders;
|
using Artemis.Core.ScriptingProviders;
|
||||||
using Artemis.UI.Routing;
|
|
||||||
using Artemis.UI.Screens.Device;
|
using Artemis.UI.Screens.Device;
|
||||||
|
using Artemis.UI.Screens.Device.General;
|
||||||
|
using Artemis.UI.Screens.Device.InputMappings;
|
||||||
|
using Artemis.UI.Screens.Device.Layout;
|
||||||
|
using Artemis.UI.Screens.Device.Leds;
|
||||||
using Artemis.UI.Screens.Plugins;
|
using Artemis.UI.Screens.Plugins;
|
||||||
using Artemis.UI.Screens.Plugins.Features;
|
using Artemis.UI.Screens.Plugins.Features;
|
||||||
using Artemis.UI.Screens.Plugins.Prerequisites;
|
using Artemis.UI.Screens.Plugins.Prerequisites;
|
||||||
@ -27,12 +28,8 @@ using Artemis.UI.Screens.Sidebar;
|
|||||||
using Artemis.UI.Screens.SurfaceEditor;
|
using Artemis.UI.Screens.SurfaceEditor;
|
||||||
using Artemis.UI.Screens.VisualScripting;
|
using Artemis.UI.Screens.VisualScripting;
|
||||||
using Artemis.UI.Screens.VisualScripting.Pins;
|
using Artemis.UI.Screens.VisualScripting.Pins;
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using Artemis.UI.Shared.Routing;
|
|
||||||
using Artemis.WebClient.Updating;
|
using Artemis.WebClient.Updating;
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
using DynamicData;
|
|
||||||
using Material.Icons;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.DryIoc.Factories;
|
namespace Artemis.UI.DryIoc.Factories;
|
||||||
@ -51,6 +48,7 @@ public interface IDeviceVmFactory : IVmFactory
|
|||||||
InputMappingsTabViewModel InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds);
|
InputMappingsTabViewModel InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds);
|
||||||
DeviceGeneralTabViewModel DeviceGeneralTabViewModel(ArtemisDevice device);
|
DeviceGeneralTabViewModel DeviceGeneralTabViewModel(ArtemisDevice device);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DeviceFactory : IDeviceVmFactory
|
public class DeviceFactory : IDeviceVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -62,37 +60,37 @@ public class DeviceFactory : IDeviceVmFactory
|
|||||||
|
|
||||||
public DevicePropertiesViewModel DevicePropertiesViewModel(ArtemisDevice device)
|
public DevicePropertiesViewModel DevicePropertiesViewModel(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DevicePropertiesViewModel>(new object[] { device });
|
return _container.Resolve<DevicePropertiesViewModel>(new object[] {device});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceSettingsViewModel DeviceSettingsViewModel(ArtemisDevice device, DevicesTabViewModel devicesTabViewModel)
|
public DeviceSettingsViewModel DeviceSettingsViewModel(ArtemisDevice device, DevicesTabViewModel devicesTabViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DeviceSettingsViewModel>(new object[] { device, devicesTabViewModel });
|
return _container.Resolve<DeviceSettingsViewModel>(new object[] {device, devicesTabViewModel});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceDetectInputViewModel DeviceDetectInputViewModel(ArtemisDevice device)
|
public DeviceDetectInputViewModel DeviceDetectInputViewModel(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DeviceDetectInputViewModel>(new object[] { device });
|
return _container.Resolve<DeviceDetectInputViewModel>(new object[] {device});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceLayoutTabViewModel DeviceLayoutTabViewModel(ArtemisDevice device)
|
public DeviceLayoutTabViewModel DeviceLayoutTabViewModel(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DeviceLayoutTabViewModel>(new object[] { device });
|
return _container.Resolve<DeviceLayoutTabViewModel>(new object[] {device});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceLedsTabViewModel DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds)
|
public DeviceLedsTabViewModel DeviceLedsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DeviceLedsTabViewModel>(new object[] { device, selectedLeds });
|
return _container.Resolve<DeviceLedsTabViewModel>(new object[] {device, selectedLeds});
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputMappingsTabViewModel InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds)
|
public InputMappingsTabViewModel InputMappingsTabViewModel(ArtemisDevice device, ObservableCollection<ArtemisLed> selectedLeds)
|
||||||
{
|
{
|
||||||
return _container.Resolve<InputMappingsTabViewModel>(new object[] { device, selectedLeds });
|
return _container.Resolve<InputMappingsTabViewModel>(new object[] {device, selectedLeds});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceGeneralTabViewModel DeviceGeneralTabViewModel(ArtemisDevice device)
|
public DeviceGeneralTabViewModel DeviceGeneralTabViewModel(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DeviceGeneralTabViewModel>(new object[] { device });
|
return _container.Resolve<DeviceGeneralTabViewModel>(new object[] {device});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +100,7 @@ public interface ISettingsVmFactory : IVmFactory
|
|||||||
PluginViewModel PluginViewModel(Plugin plugin, ReactiveCommand<Unit, Unit>? reload);
|
PluginViewModel PluginViewModel(Plugin plugin, ReactiveCommand<Unit, Unit>? reload);
|
||||||
PluginFeatureViewModel PluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo, bool showShield);
|
PluginFeatureViewModel PluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo, bool showShield);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SettingsVmFactory : ISettingsVmFactory
|
public class SettingsVmFactory : ISettingsVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -113,17 +112,17 @@ public class SettingsVmFactory : ISettingsVmFactory
|
|||||||
|
|
||||||
public PluginSettingsViewModel PluginSettingsViewModel(Plugin plugin)
|
public PluginSettingsViewModel PluginSettingsViewModel(Plugin plugin)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PluginSettingsViewModel>(new object[] { plugin });
|
return _container.Resolve<PluginSettingsViewModel>(new object[] {plugin});
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginViewModel PluginViewModel(Plugin plugin, ReactiveCommand<Unit, Unit>? reload)
|
public PluginViewModel PluginViewModel(Plugin plugin, ReactiveCommand<Unit, Unit>? reload)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PluginViewModel>(new object?[] { plugin, reload });
|
return _container.Resolve<PluginViewModel>(new object?[] {plugin, reload});
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginFeatureViewModel PluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo, bool showShield)
|
public PluginFeatureViewModel PluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo, bool showShield)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PluginFeatureViewModel>(new object[] { pluginFeatureInfo, showShield });
|
return _container.Resolve<PluginFeatureViewModel>(new object[] {pluginFeatureInfo, showShield});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,6 +131,7 @@ public interface ISidebarVmFactory : IVmFactory
|
|||||||
SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory);
|
SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory);
|
||||||
SidebarProfileConfigurationViewModel SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration);
|
SidebarProfileConfigurationViewModel SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SidebarVmFactory : ISidebarVmFactory
|
public class SidebarVmFactory : ISidebarVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -143,12 +143,12 @@ public class SidebarVmFactory : ISidebarVmFactory
|
|||||||
|
|
||||||
public SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory)
|
public SidebarCategoryViewModel SidebarCategoryViewModel(ProfileCategory profileCategory)
|
||||||
{
|
{
|
||||||
return _container.Resolve<SidebarCategoryViewModel>(new object[] { profileCategory });
|
return _container.Resolve<SidebarCategoryViewModel>(new object[] {profileCategory});
|
||||||
}
|
}
|
||||||
|
|
||||||
public SidebarProfileConfigurationViewModel SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration)
|
public SidebarProfileConfigurationViewModel SidebarProfileConfigurationViewModel(ProfileConfiguration profileConfiguration)
|
||||||
{
|
{
|
||||||
return _container.Resolve<SidebarProfileConfigurationViewModel>(new object[] { profileConfiguration });
|
return _container.Resolve<SidebarProfileConfigurationViewModel>(new object[] {profileConfiguration});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +157,7 @@ public interface ISurfaceVmFactory : IVmFactory
|
|||||||
SurfaceDeviceViewModel SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel);
|
SurfaceDeviceViewModel SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel);
|
||||||
ListDeviceViewModel ListDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel);
|
ListDeviceViewModel ListDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SurfaceVmFactory : ISurfaceVmFactory
|
public class SurfaceVmFactory : ISurfaceVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -168,12 +169,12 @@ public class SurfaceVmFactory : ISurfaceVmFactory
|
|||||||
|
|
||||||
public SurfaceDeviceViewModel SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel)
|
public SurfaceDeviceViewModel SurfaceDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<SurfaceDeviceViewModel>(new object[] { device, surfaceEditorViewModel });
|
return _container.Resolve<SurfaceDeviceViewModel>(new object[] {device, surfaceEditorViewModel});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListDeviceViewModel ListDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel)
|
public ListDeviceViewModel ListDeviceViewModel(ArtemisDevice device, SurfaceEditorViewModel surfaceEditorViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<ListDeviceViewModel>(new object[] { device, surfaceEditorViewModel });
|
return _container.Resolve<ListDeviceViewModel>(new object[] {device, surfaceEditorViewModel});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,6 +182,7 @@ public interface IPrerequisitesVmFactory : IVmFactory
|
|||||||
{
|
{
|
||||||
PluginPrerequisiteViewModel PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall);
|
PluginPrerequisiteViewModel PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PrerequisitesVmFactory : IPrerequisitesVmFactory
|
public class PrerequisitesVmFactory : IPrerequisitesVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -192,7 +194,7 @@ public class PrerequisitesVmFactory : IPrerequisitesVmFactory
|
|||||||
|
|
||||||
public PluginPrerequisiteViewModel PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall)
|
public PluginPrerequisiteViewModel PluginPrerequisiteViewModel(PluginPrerequisite pluginPrerequisite, bool uninstall)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PluginPrerequisiteViewModel>(new object[] { pluginPrerequisite, uninstall });
|
return _container.Resolve<PluginPrerequisiteViewModel>(new object[] {pluginPrerequisite, uninstall});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,6 +206,7 @@ public interface IProfileEditorVmFactory : IVmFactory
|
|||||||
LayerShapeVisualizerViewModel LayerShapeVisualizerViewModel(Layer layer);
|
LayerShapeVisualizerViewModel LayerShapeVisualizerViewModel(Layer layer);
|
||||||
LayerVisualizerViewModel LayerVisualizerViewModel(Layer layer);
|
LayerVisualizerViewModel LayerVisualizerViewModel(Layer layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ProfileEditorVmFactory : IProfileEditorVmFactory
|
public class ProfileEditorVmFactory : IProfileEditorVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -215,27 +218,27 @@ public class ProfileEditorVmFactory : IProfileEditorVmFactory
|
|||||||
|
|
||||||
public FolderTreeItemViewModel FolderTreeItemViewModel(TreeItemViewModel? parent, Folder folder)
|
public FolderTreeItemViewModel FolderTreeItemViewModel(TreeItemViewModel? parent, Folder folder)
|
||||||
{
|
{
|
||||||
return _container.Resolve<FolderTreeItemViewModel>(new object?[] { parent, folder });
|
return _container.Resolve<FolderTreeItemViewModel>(new object?[] {parent, folder});
|
||||||
}
|
}
|
||||||
|
|
||||||
public LayerShapeVisualizerViewModel LayerShapeVisualizerViewModel(Layer layer)
|
public LayerShapeVisualizerViewModel LayerShapeVisualizerViewModel(Layer layer)
|
||||||
{
|
{
|
||||||
return _container.Resolve<LayerShapeVisualizerViewModel>(new object[] { layer });
|
return _container.Resolve<LayerShapeVisualizerViewModel>(new object[] {layer});
|
||||||
}
|
}
|
||||||
|
|
||||||
public LayerTreeItemViewModel LayerTreeItemViewModel(TreeItemViewModel? parent, Layer layer)
|
public LayerTreeItemViewModel LayerTreeItemViewModel(TreeItemViewModel? parent, Layer layer)
|
||||||
{
|
{
|
||||||
return _container.Resolve<LayerTreeItemViewModel>(new object?[] { parent, layer });
|
return _container.Resolve<LayerTreeItemViewModel>(new object?[] {parent, layer});
|
||||||
}
|
}
|
||||||
|
|
||||||
public LayerVisualizerViewModel LayerVisualizerViewModel(Layer layer)
|
public LayerVisualizerViewModel LayerVisualizerViewModel(Layer layer)
|
||||||
{
|
{
|
||||||
return _container.Resolve<LayerVisualizerViewModel>(new object[] { layer });
|
return _container.Resolve<LayerVisualizerViewModel>(new object[] {layer});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProfileEditorViewModel ProfileEditorViewModel(IScreen hostScreen)
|
public ProfileEditorViewModel ProfileEditorViewModel(IScreen hostScreen)
|
||||||
{
|
{
|
||||||
return _container.Resolve<ProfileEditorViewModel>(new object[] { hostScreen });
|
return _container.Resolve<ProfileEditorViewModel>(new object[] {hostScreen});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +254,7 @@ public interface ILayerPropertyVmFactory : IVmFactory
|
|||||||
TimelineViewModel TimelineViewModel(ObservableCollection<PropertyGroupViewModel> propertyGroupViewModels);
|
TimelineViewModel TimelineViewModel(ObservableCollection<PropertyGroupViewModel> propertyGroupViewModels);
|
||||||
TimelineGroupViewModel TimelineGroupViewModel(PropertyGroupViewModel propertyGroupViewModel);
|
TimelineGroupViewModel TimelineGroupViewModel(PropertyGroupViewModel propertyGroupViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LayerPropertyVmFactory : ILayerPropertyVmFactory
|
public class LayerPropertyVmFactory : ILayerPropertyVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -262,37 +266,37 @@ public class LayerPropertyVmFactory : ILayerPropertyVmFactory
|
|||||||
|
|
||||||
public PropertyViewModel PropertyViewModel(ILayerProperty layerProperty)
|
public PropertyViewModel PropertyViewModel(ILayerProperty layerProperty)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PropertyViewModel>(new object[] { layerProperty });
|
return _container.Resolve<PropertyViewModel>(new object[] {layerProperty});
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyGroupViewModel PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup)
|
public PropertyGroupViewModel PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PropertyGroupViewModel>(new object[] { layerPropertyGroup });
|
return _container.Resolve<PropertyGroupViewModel>(new object[] {layerPropertyGroup});
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyGroupViewModel PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, BaseLayerBrush layerBrush)
|
public PropertyGroupViewModel PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, BaseLayerBrush layerBrush)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PropertyGroupViewModel>(new object[] { layerPropertyGroup, layerBrush });
|
return _container.Resolve<PropertyGroupViewModel>(new object[] {layerPropertyGroup, layerBrush});
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyGroupViewModel PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, BaseLayerEffect layerEffect)
|
public PropertyGroupViewModel PropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, BaseLayerEffect layerEffect)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PropertyGroupViewModel>(new object[] { layerPropertyGroup, layerEffect });
|
return _container.Resolve<PropertyGroupViewModel>(new object[] {layerPropertyGroup, layerEffect});
|
||||||
}
|
}
|
||||||
|
|
||||||
public TreeGroupViewModel TreeGroupViewModel(PropertyGroupViewModel propertyGroupViewModel)
|
public TreeGroupViewModel TreeGroupViewModel(PropertyGroupViewModel propertyGroupViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<TreeGroupViewModel>(new object[] { propertyGroupViewModel });
|
return _container.Resolve<TreeGroupViewModel>(new object[] {propertyGroupViewModel});
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimelineViewModel TimelineViewModel(ObservableCollection<PropertyGroupViewModel> propertyGroupViewModels)
|
public TimelineViewModel TimelineViewModel(ObservableCollection<PropertyGroupViewModel> propertyGroupViewModels)
|
||||||
{
|
{
|
||||||
return _container.Resolve<TimelineViewModel>(new object[] { propertyGroupViewModels });
|
return _container.Resolve<TimelineViewModel>(new object[] {propertyGroupViewModels});
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimelineGroupViewModel TimelineGroupViewModel(PropertyGroupViewModel propertyGroupViewModel)
|
public TimelineGroupViewModel TimelineGroupViewModel(PropertyGroupViewModel propertyGroupViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<TimelineGroupViewModel>(new object[] { propertyGroupViewModel });
|
return _container.Resolve<TimelineGroupViewModel>(new object[] {propertyGroupViewModel});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,6 +304,7 @@ public interface IDataBindingVmFactory : IVmFactory
|
|||||||
{
|
{
|
||||||
DataBindingViewModel DataBindingViewModel();
|
DataBindingViewModel DataBindingViewModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DataBindingVmFactory : IDataBindingVmFactory
|
public class DataBindingVmFactory : IDataBindingVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -333,6 +338,7 @@ public interface INodeVmFactory : IVmFactory
|
|||||||
InputPinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
InputPinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
||||||
OutputPinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
OutputPinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NodeVmFactory : INodeVmFactory
|
public class NodeVmFactory : INodeVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -344,47 +350,47 @@ public class NodeVmFactory : INodeVmFactory
|
|||||||
|
|
||||||
public NodeScriptViewModel NodeScriptViewModel(NodeScript nodeScript, bool isPreview)
|
public NodeScriptViewModel NodeScriptViewModel(NodeScript nodeScript, bool isPreview)
|
||||||
{
|
{
|
||||||
return _container.Resolve<NodeScriptViewModel>(new object[] { nodeScript, isPreview });
|
return _container.Resolve<NodeScriptViewModel>(new object[] {nodeScript, isPreview});
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodePickerViewModel NodePickerViewModel(NodeScript nodeScript)
|
public NodePickerViewModel NodePickerViewModel(NodeScript nodeScript)
|
||||||
{
|
{
|
||||||
return _container.Resolve<NodePickerViewModel>(new object[] { nodeScript });
|
return _container.Resolve<NodePickerViewModel>(new object[] {nodeScript});
|
||||||
}
|
}
|
||||||
|
|
||||||
public NodeViewModel NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node)
|
public NodeViewModel NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node)
|
||||||
{
|
{
|
||||||
return _container.Resolve<NodeViewModel>(new object[] { nodeScriptViewModel, node });
|
return _container.Resolve<NodeViewModel>(new object[] {nodeScriptViewModel, node});
|
||||||
}
|
}
|
||||||
|
|
||||||
public CableViewModel CableViewModel(NodeScriptViewModel nodeScriptViewModel, IPin from, IPin to)
|
public CableViewModel CableViewModel(NodeScriptViewModel nodeScriptViewModel, IPin from, IPin to)
|
||||||
{
|
{
|
||||||
return _container.Resolve<CableViewModel>(new object[] { nodeScriptViewModel, from, to });
|
return _container.Resolve<CableViewModel>(new object[] {nodeScriptViewModel, from, to});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DragCableViewModel DragCableViewModel(PinViewModel pinViewModel)
|
public DragCableViewModel DragCableViewModel(PinViewModel pinViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DragCableViewModel>(new object[] { pinViewModel });
|
return _container.Resolve<DragCableViewModel>(new object[] {pinViewModel});
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputPinViewModel InputPinViewModel(IPin inputPin, NodeScriptViewModel nodeScriptViewModel)
|
public InputPinViewModel InputPinViewModel(IPin inputPin, NodeScriptViewModel nodeScriptViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<InputPinViewModel>(new object[] { inputPin, nodeScriptViewModel });
|
return _container.Resolve<InputPinViewModel>(new object[] {inputPin, nodeScriptViewModel});
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputPinViewModel OutputPinViewModel(IPin outputPin, NodeScriptViewModel nodeScriptViewModel)
|
public OutputPinViewModel OutputPinViewModel(IPin outputPin, NodeScriptViewModel nodeScriptViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<OutputPinViewModel>(new object[] { outputPin, nodeScriptViewModel });
|
return _container.Resolve<OutputPinViewModel>(new object[] {outputPin, nodeScriptViewModel});
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputPinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel)
|
public InputPinCollectionViewModel InputPinCollectionViewModel(IPinCollection inputPinCollection, NodeScriptViewModel nodeScriptViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<InputPinCollectionViewModel>(new object[] { inputPinCollection, nodeScriptViewModel });
|
return _container.Resolve<InputPinCollectionViewModel>(new object[] {inputPinCollection, nodeScriptViewModel});
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutputPinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel)
|
public OutputPinCollectionViewModel OutputPinCollectionViewModel(IPinCollection outputPinCollection, NodeScriptViewModel nodeScriptViewModel)
|
||||||
{
|
{
|
||||||
return _container.Resolve<OutputPinCollectionViewModel>(new object[] { outputPinCollection, nodeScriptViewModel });
|
return _container.Resolve<OutputPinCollectionViewModel>(new object[] {outputPinCollection, nodeScriptViewModel});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +401,7 @@ public interface IConditionVmFactory : IVmFactory
|
|||||||
StaticConditionViewModel StaticConditionViewModel(StaticCondition staticCondition);
|
StaticConditionViewModel StaticConditionViewModel(StaticCondition staticCondition);
|
||||||
EventConditionViewModel EventConditionViewModel(EventCondition eventCondition);
|
EventConditionViewModel EventConditionViewModel(EventCondition eventCondition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ConditionVmFactory : IConditionVmFactory
|
public class ConditionVmFactory : IConditionVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -406,22 +413,22 @@ public class ConditionVmFactory : IConditionVmFactory
|
|||||||
|
|
||||||
public AlwaysOnConditionViewModel AlwaysOnConditionViewModel(AlwaysOnCondition alwaysOnCondition)
|
public AlwaysOnConditionViewModel AlwaysOnConditionViewModel(AlwaysOnCondition alwaysOnCondition)
|
||||||
{
|
{
|
||||||
return _container.Resolve<AlwaysOnConditionViewModel>(new object[] { alwaysOnCondition });
|
return _container.Resolve<AlwaysOnConditionViewModel>(new object[] {alwaysOnCondition});
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayOnceConditionViewModel PlayOnceConditionViewModel(PlayOnceCondition playOnceCondition)
|
public PlayOnceConditionViewModel PlayOnceConditionViewModel(PlayOnceCondition playOnceCondition)
|
||||||
{
|
{
|
||||||
return _container.Resolve<PlayOnceConditionViewModel>(new object[] { playOnceCondition });
|
return _container.Resolve<PlayOnceConditionViewModel>(new object[] {playOnceCondition});
|
||||||
}
|
}
|
||||||
|
|
||||||
public StaticConditionViewModel StaticConditionViewModel(StaticCondition staticCondition)
|
public StaticConditionViewModel StaticConditionViewModel(StaticCondition staticCondition)
|
||||||
{
|
{
|
||||||
return _container.Resolve<StaticConditionViewModel>(new object[] { staticCondition });
|
return _container.Resolve<StaticConditionViewModel>(new object[] {staticCondition});
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventConditionViewModel EventConditionViewModel(EventCondition eventCondition)
|
public EventConditionViewModel EventConditionViewModel(EventCondition eventCondition)
|
||||||
{
|
{
|
||||||
return _container.Resolve<EventConditionViewModel>(new object[] { eventCondition });
|
return _container.Resolve<EventConditionViewModel>(new object[] {eventCondition});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,6 +439,7 @@ public interface ILayerHintVmFactory : IVmFactory
|
|||||||
KeyboardSectionAdaptionHintViewModel KeyboardSectionAdaptionHintViewModel(Layer layer, KeyboardSectionAdaptionHint adaptionHint);
|
KeyboardSectionAdaptionHintViewModel KeyboardSectionAdaptionHintViewModel(Layer layer, KeyboardSectionAdaptionHint adaptionHint);
|
||||||
SingleLedAdaptionHintViewModel SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint);
|
SingleLedAdaptionHintViewModel SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LayerHintVmFactory : ILayerHintVmFactory
|
public class LayerHintVmFactory : ILayerHintVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -443,22 +451,22 @@ public class LayerHintVmFactory : ILayerHintVmFactory
|
|||||||
|
|
||||||
public CategoryAdaptionHintViewModel CategoryAdaptionHintViewModel(Layer layer, CategoryAdaptionHint adaptionHint)
|
public CategoryAdaptionHintViewModel CategoryAdaptionHintViewModel(Layer layer, CategoryAdaptionHint adaptionHint)
|
||||||
{
|
{
|
||||||
return _container.Resolve<CategoryAdaptionHintViewModel>(new object[] { layer, adaptionHint });
|
return _container.Resolve<CategoryAdaptionHintViewModel>(new object[] {layer, adaptionHint});
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeviceAdaptionHintViewModel DeviceAdaptionHintViewModel(Layer layer, DeviceAdaptionHint adaptionHint)
|
public DeviceAdaptionHintViewModel DeviceAdaptionHintViewModel(Layer layer, DeviceAdaptionHint adaptionHint)
|
||||||
{
|
{
|
||||||
return _container.Resolve<DeviceAdaptionHintViewModel>(new object[] { layer, adaptionHint });
|
return _container.Resolve<DeviceAdaptionHintViewModel>(new object[] {layer, adaptionHint});
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyboardSectionAdaptionHintViewModel KeyboardSectionAdaptionHintViewModel(Layer layer, KeyboardSectionAdaptionHint adaptionHint)
|
public KeyboardSectionAdaptionHintViewModel KeyboardSectionAdaptionHintViewModel(Layer layer, KeyboardSectionAdaptionHint adaptionHint)
|
||||||
{
|
{
|
||||||
return _container.Resolve<KeyboardSectionAdaptionHintViewModel>(new object[] { layer, adaptionHint });
|
return _container.Resolve<KeyboardSectionAdaptionHintViewModel>(new object[] {layer, adaptionHint});
|
||||||
}
|
}
|
||||||
|
|
||||||
public SingleLedAdaptionHintViewModel SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint)
|
public SingleLedAdaptionHintViewModel SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint)
|
||||||
{
|
{
|
||||||
return _container.Resolve<SingleLedAdaptionHintViewModel>(new object[] { layer, adaptionHint });
|
return _container.Resolve<SingleLedAdaptionHintViewModel>(new object[] {layer, adaptionHint});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,6 +475,7 @@ public interface IScriptVmFactory : IVmFactory
|
|||||||
ScriptConfigurationViewModel ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration);
|
ScriptConfigurationViewModel ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration);
|
||||||
ScriptConfigurationViewModel ScriptConfigurationViewModel(Profile profile, ScriptConfiguration scriptConfiguration);
|
ScriptConfigurationViewModel ScriptConfigurationViewModel(Profile profile, ScriptConfiguration scriptConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ScriptVmFactory : IScriptVmFactory
|
public class ScriptVmFactory : IScriptVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -478,12 +487,12 @@ public class ScriptVmFactory : IScriptVmFactory
|
|||||||
|
|
||||||
public ScriptConfigurationViewModel ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration)
|
public ScriptConfigurationViewModel ScriptConfigurationViewModel(ScriptConfiguration scriptConfiguration)
|
||||||
{
|
{
|
||||||
return _container.Resolve<ScriptConfigurationViewModel>(new object[] { scriptConfiguration });
|
return _container.Resolve<ScriptConfigurationViewModel>(new object[] {scriptConfiguration});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptConfigurationViewModel ScriptConfigurationViewModel(Profile profile, ScriptConfiguration scriptConfiguration)
|
public ScriptConfigurationViewModel ScriptConfigurationViewModel(Profile profile, ScriptConfiguration scriptConfiguration)
|
||||||
{
|
{
|
||||||
return _container.Resolve<ScriptConfigurationViewModel>(new object[] { profile, scriptConfiguration });
|
return _container.Resolve<ScriptConfigurationViewModel>(new object[] {profile, scriptConfiguration});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,6 +500,7 @@ public interface IReleaseVmFactory : IVmFactory
|
|||||||
{
|
{
|
||||||
ReleaseViewModel ReleaseListViewModel(IGetReleases_PublishedReleases_Nodes release);
|
ReleaseViewModel ReleaseListViewModel(IGetReleases_PublishedReleases_Nodes release);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReleaseVmFactory : IReleaseVmFactory
|
public class ReleaseVmFactory : IReleaseVmFactory
|
||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
@ -502,6 +512,6 @@ public class ReleaseVmFactory : IReleaseVmFactory
|
|||||||
|
|
||||||
public ReleaseViewModel ReleaseListViewModel(IGetReleases_PublishedReleases_Nodes release)
|
public ReleaseViewModel ReleaseListViewModel(IGetReleases_PublishedReleases_Nodes release)
|
||||||
{
|
{
|
||||||
return _container.Resolve<ReleaseViewModel>(new object[] { release });
|
return _container.Resolve<ReleaseViewModel>(new object[] {release});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5,9 +5,10 @@
|
|||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="650"
|
||||||
x:Class="Artemis.UI.Screens.Device.DeviceGeneralTabView"
|
x:Class="Artemis.UI.Screens.Device.General.DeviceGeneralTabView"
|
||||||
x:DataType="device:DeviceGeneralTabViewModel">
|
x:DataType="general:DeviceGeneralTabViewModel">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.General;
|
||||||
public partial class DeviceGeneralTabView : ReactiveUserControl<DeviceGeneralTabViewModel>
|
public partial class DeviceGeneralTabView : ReactiveUserControl<DeviceGeneralTabViewModel>
|
||||||
{
|
{
|
||||||
public DeviceGeneralTabView()
|
public DeviceGeneralTabView()
|
||||||
@ -4,6 +4,7 @@ using System.Reactive.Disposables;
|
|||||||
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.Screens.Device.Layout;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using PropertyChanged.SourceGenerator;
|
using PropertyChanged.SourceGenerator;
|
||||||
@ -11,7 +12,7 @@ using ReactiveUI;
|
|||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.General;
|
||||||
|
|
||||||
public partial class DeviceGeneralTabViewModel : ActivatableViewModelBase
|
public partial class DeviceGeneralTabViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
@ -56,7 +57,7 @@ public partial class DeviceGeneralTabViewModel : ActivatableViewModelBase
|
|||||||
_initialGreenScale = Device.GreenScale;
|
_initialGreenScale = Device.GreenScale;
|
||||||
_initialBlueScale = Device.BlueScale;
|
_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 =>
|
this.WhenActivated(d =>
|
||||||
{
|
{
|
||||||
@ -127,12 +128,12 @@ public partial class DeviceGeneralTabViewModel : ActivatableViewModelBase
|
|||||||
return;
|
return;
|
||||||
if (!Device.DeviceProvider.CanDetectPhysicalLayout && !await DevicePhysicalLayoutDialogViewModel.SelectPhysicalLayout(_windowService, Device))
|
if (!Device.DeviceProvider.CanDetectPhysicalLayout && !await DevicePhysicalLayoutDialogViewModel.SelectPhysicalLayout(_windowService, Device))
|
||||||
return;
|
return;
|
||||||
if (!Device.DeviceProvider.CanDetectLogicalLayout && !await DeviceLogicalLayoutDialogViewModel.SelectLogicalLayout(_windowService, Device))
|
if (!Device.DeviceProvider.CanDetectLogicalLayout && !await Layout.DeviceLogicalLayoutDialogViewModel.SelectLogicalLayout(_windowService, Device))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await Task.Delay(400);
|
await Task.Delay(400);
|
||||||
_deviceService.SaveDevice(Device);
|
_deviceService.SaveDevice(Device);
|
||||||
_deviceService.ApplyDeviceLayout(Device, Device.GetBestDeviceLayout());
|
_deviceService.LoadDeviceLayout(Device);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Apply()
|
private void Apply()
|
||||||
@ -4,9 +4,10 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Device.InputMappingsTabView"
|
x:Class="Artemis.UI.Screens.Device.InputMappings.InputMappingsTabView"
|
||||||
x:DataType="device:InputMappingsTabViewModel">
|
x:DataType="inputMappings:InputMappingsTabViewModel">
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
<Grid RowDefinitions="Auto,Auto,*">
|
<Grid RowDefinitions="Auto,Auto,*">
|
||||||
<StackPanel Grid.Row="0">
|
<StackPanel Grid.Row="0">
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.InputMappings;
|
||||||
|
|
||||||
public partial class InputMappingsTabView : ReactiveUserControl<InputMappingsTabViewModel>
|
public partial class InputMappingsTabView : ReactiveUserControl<InputMappingsTabViewModel>
|
||||||
{
|
{
|
||||||
@ -6,13 +6,12 @@ using Artemis.Core;
|
|||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Exceptions;
|
using Artemis.UI.Exceptions;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using HidSharp.Reports.Units;
|
|
||||||
using PropertyChanged.SourceGenerator;
|
using PropertyChanged.SourceGenerator;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
using Unit = System.Reactive.Unit;
|
using Unit = System.Reactive.Unit;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.InputMappings;
|
||||||
|
|
||||||
public partial class InputMappingsTabViewModel : ActivatableViewModelBase
|
public partial class InputMappingsTabViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
@ -5,9 +5,12 @@
|
|||||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800"
|
||||||
x:Class="Artemis.UI.Screens.Device.DeviceLayoutTabView"
|
x:Class="Artemis.UI.Screens.Device.Layout.DeviceLayoutTabView"
|
||||||
x:DataType="device:DeviceLayoutTabViewModel">
|
x:DataType="layout:DeviceLayoutTabViewModel">
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
<Border Classes="card" Margin="5">
|
<Border Classes="card" Margin="5">
|
||||||
<Grid RowDefinitions="*,Auto">
|
<Grid RowDefinitions="*,Auto">
|
||||||
@ -28,6 +31,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Border Classes="card-separator" />
|
<Border Classes="card-separator" />
|
||||||
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
<StackPanel Grid.Row="1" Grid.Column="0">
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
@ -45,28 +49,43 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Border Classes="card-separator" />
|
<Border Classes="card-separator" />
|
||||||
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
<Grid RowDefinitions="*,*,*" ColumnDefinitions="*,Auto">
|
||||||
<StackPanel Grid.Row="1" Grid.Column="0">
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
<TextBlock Text="Disable default layout" />
|
<TextBlock Text="Layout provider" />
|
||||||
<TextBlock Classes="subtitle" FontSize="12" Text="With this checked, Artemis will not load a layout for this device unless you specifically provide one." />
|
<TextBlock Classes="subtitle" FontSize="12" Text="Choose between different ways to load a layout for this device." />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center">
|
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center">
|
||||||
<CheckBox HorizontalAlignment="Right" Margin="0,0,-10,0" IsChecked="{CompiledBinding Device.DisableDefaultLayout}"/>
|
<StackPanel.Styles>
|
||||||
</StackPanel>
|
<Style Selector="ComboBox.layoutProvider /template/ ContentControl#ContentPresenter">
|
||||||
</Grid>
|
<Setter Property="ContentTemplate">
|
||||||
<Border Classes="card-separator" />
|
<Setter.Value>
|
||||||
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
<DataTemplate x:DataType="layoutProviders:ILayoutProviderViewModel">
|
||||||
<StackPanel Grid.Row="1" Grid.Column="0">
|
<TextBlock Text="{CompiledBinding Name}" TextWrapping="Wrap" MaxWidth="350" />
|
||||||
<TextBlock Text="Custom layout path" />
|
</DataTemplate>
|
||||||
<TextBlock Classes="subtitle" FontSize="12" Text="{CompiledBinding CustomLayoutPath, TargetNullValue=None}"/>
|
</Setter.Value>
|
||||||
</StackPanel>
|
</Setter>
|
||||||
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Orientation="Horizontal">
|
</Style>
|
||||||
<Button Content="Clear" Command="{CompiledBinding ClearCustomLayout}" IsEnabled="{CompiledBinding HasCustomLayout}" />
|
</StackPanel.Styles>
|
||||||
<!-- 5 pixels of margin between the buttons -->
|
<ComboBox Classes="layoutProvider"
|
||||||
<Button Margin="5,0,0,0" Content="Browse" Command="{CompiledBinding BrowseCustomLayout}" />
|
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>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<ContentControl Content="{CompiledBinding SelectedLayoutProvider}" ClipToBounds="False"></ContentControl>
|
||||||
|
|
||||||
<Border Classes="card-separator" />
|
<Border Classes="card-separator" />
|
||||||
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
<Grid RowDefinitions="*,*" ColumnDefinitions="*,Auto">
|
||||||
<StackPanel Grid.Row="1" Grid.Column="0">
|
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||||
@ -2,7 +2,7 @@
|
|||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.Layout;
|
||||||
|
|
||||||
public partial class DeviceLayoutTabView : ReactiveUserControl<DeviceLayoutTabViewModel>
|
public partial class DeviceLayoutTabView : ReactiveUserControl<DeviceLayoutTabViewModel>
|
||||||
{
|
{
|
||||||
@ -1,81 +1,52 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive.Disposables;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Services.Builders;
|
using Artemis.UI.Shared.Services.Builders;
|
||||||
using Avalonia.Controls;
|
using PropertyChanged.SourceGenerator;
|
||||||
using ReactiveUI;
|
|
||||||
using RGB.NET.Layout;
|
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 IWindowService _windowService;
|
||||||
private readonly INotificationService _notificationService;
|
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;
|
_windowService = windowService;
|
||||||
_notificationService = notificationService;
|
_notificationService = notificationService;
|
||||||
_deviceService = deviceService;
|
|
||||||
|
|
||||||
Device = device;
|
Device = device;
|
||||||
DisplayName = "Layout";
|
DisplayName = "Layout";
|
||||||
DefaultLayoutPath = Device.DeviceProvider.LoadLayout(Device).FilePath;
|
DefaultLayoutPath = Device.DeviceProvider.LoadLayout(Device).FilePath;
|
||||||
|
|
||||||
this.WhenActivated(d =>
|
LayoutProviders = new ObservableCollection<ILayoutProviderViewModel>(layoutProviders);
|
||||||
|
foreach (ILayoutProviderViewModel layoutProviderViewModel in layoutProviders)
|
||||||
{
|
{
|
||||||
Device.PropertyChanged += DeviceOnPropertyChanged;
|
layoutProviderViewModel.Device = Device;
|
||||||
Disposable.Create(() => Device.PropertyChanged -= DeviceOnPropertyChanged).DisposeWith(d);
|
if (layoutProviderViewModel.IsMatch(Device))
|
||||||
});
|
SelectedLayoutProvider = layoutProviderViewModel;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisDevice Device { get; }
|
public ArtemisDevice Device { get; }
|
||||||
|
public ObservableCollection<ILayoutProviderViewModel> LayoutProviders { get; set; }
|
||||||
|
|
||||||
public string DefaultLayoutPath { get; }
|
public string DefaultLayoutPath { get; }
|
||||||
|
|
||||||
public string? ImagePath => Device.Layout?.Image?.LocalPath;
|
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()
|
public async Task ExportLayout()
|
||||||
{
|
{
|
||||||
string fileName = Device.DeviceProvider.GetDeviceLayoutName(Device);
|
string fileName = Device.DeviceProvider.GetDeviceLayoutName(Device);
|
||||||
@ -145,19 +116,4 @@ public class DeviceLayoutTabViewModel : ActivatableViewModelBase
|
|||||||
.WithSeverity(NotificationSeverity.Informational)
|
.WithSeverity(NotificationSeverity.Informational)
|
||||||
.Show();
|
.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
||||||
xmlns:globalization="clr-namespace:System.Globalization;assembly=System.Runtime"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Device.DeviceLogicalLayoutDialogView"
|
x:Class="Artemis.UI.Screens.Device.Layout.DeviceLogicalLayoutDialogView"
|
||||||
x:DataType="device:DeviceLogicalLayoutDialogViewModel">
|
x:DataType="layout:DeviceLogicalLayoutDialogViewModel">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock TextWrapping="Wrap">Artemis couldn't automatically determine the logical layout of your</TextBlock>
|
<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}" />
|
<TextBlock TextWrapping="Wrap" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.DeviceName, Mode=OneWay}" />
|
||||||
@ -1,12 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.Layout;
|
||||||
|
|
||||||
public partial class DeviceLogicalLayoutDialogView : ReactiveUserControl<DeviceLogicalLayoutDialogViewModel>
|
public partial class DeviceLogicalLayoutDialogView : ReactiveUserControl<DeviceLogicalLayoutDialogViewModel>
|
||||||
{
|
{
|
||||||
@ -12,7 +12,7 @@ using PropertyChanged.SourceGenerator;
|
|||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ContentDialogButton = Artemis.UI.Shared.Services.Builders.ContentDialogButton;
|
using ContentDialogButton = Artemis.UI.Shared.Services.Builders.ContentDialogButton;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.Layout;
|
||||||
|
|
||||||
public partial class DeviceLogicalLayoutDialogViewModel : ContentDialogViewModelBase
|
public partial class DeviceLogicalLayoutDialogViewModel : ContentDialogViewModelBase
|
||||||
{
|
{
|
||||||
@ -24,7 +24,7 @@ public partial class DeviceLogicalLayoutDialogViewModel : ContentDialogViewModel
|
|||||||
public DeviceLogicalLayoutDialogViewModel(ArtemisDevice device)
|
public DeviceLogicalLayoutDialogViewModel(ArtemisDevice device)
|
||||||
{
|
{
|
||||||
Device = 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)
|
Regions = new ObservableCollection<RegionInfo>(CultureInfo.GetCultures(CultureTypes.SpecificCultures)
|
||||||
.Where(c => c.LCID != LOCALE_INVARIANT &&
|
.Where(c => c.LCID != LOCALE_INVARIANT &&
|
||||||
c.LCID != LOCALE_NEUTRAL &&
|
c.LCID != LOCALE_NEUTRAL &&
|
||||||
@ -3,9 +3,10 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Device.DevicePhysicalLayoutDialogView"
|
x:Class="Artemis.UI.Screens.Device.Layout.DevicePhysicalLayoutDialogView"
|
||||||
x:DataType="device:DevicePhysicalLayoutDialogViewModel">
|
x:DataType="layout:DevicePhysicalLayoutDialogViewModel">
|
||||||
<Grid RowDefinitions="Auto,*">
|
<Grid RowDefinitions="Auto,*">
|
||||||
<StackPanel Grid.Row="0">
|
<StackPanel Grid.Row="0">
|
||||||
<StackPanel Orientation="Horizontal">
|
<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>
|
public partial class DevicePhysicalLayoutDialogView : ReactiveUserControl<DevicePhysicalLayoutDialogViewModel>
|
||||||
{
|
{
|
||||||
@ -7,7 +7,7 @@ using Artemis.UI.Shared.Services;
|
|||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.Layout;
|
||||||
|
|
||||||
public class DevicePhysicalLayoutDialogViewModel : ContentDialogViewModelBase
|
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.Core;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.Leds;
|
||||||
|
|
||||||
public class DeviceLedsTabLedViewModel : ViewModelBase
|
public class DeviceLedsTabLedViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
@ -5,9 +5,10 @@
|
|||||||
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
xmlns:device="clr-namespace:Artemis.UI.Screens.Device"
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:shared="clr-namespace:Artemis.UI.Shared.Converters;assembly=Artemis.UI.Shared"
|
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"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Device.DeviceLedsTabView"
|
x:Class="Artemis.UI.Screens.Device.Leds.DeviceLedsTabView"
|
||||||
x:DataType="device:DeviceLedsTabViewModel">
|
x:DataType="leds:DeviceLedsTabViewModel">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<converters:UriToFileNameConverter x:Key="UriToFileNameConverter" />
|
<converters:UriToFileNameConverter x:Key="UriToFileNameConverter" />
|
||||||
<converters:LedIdToStringConverter x:Key="LedIdToStringConverter" />
|
<converters:LedIdToStringConverter x:Key="LedIdToStringConverter" />
|
||||||
@ -1,7 +1,6 @@
|
|||||||
using Avalonia.Markup.Xaml;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.Leds;
|
||||||
|
|
||||||
public partial class DeviceLedsTabView : ReactiveUserControl<DeviceLedsTabViewModel>
|
public partial class DeviceLedsTabView : ReactiveUserControl<DeviceLedsTabViewModel>
|
||||||
{
|
{
|
||||||
@ -8,7 +8,7 @@ using Artemis.UI.Shared;
|
|||||||
using DynamicData.Binding;
|
using DynamicData.Binding;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Device;
|
namespace Artemis.UI.Screens.Device.Leds;
|
||||||
|
|
||||||
public class DeviceLedsTabViewModel : ActivatableViewModelBase
|
public class DeviceLedsTabViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
@ -46,7 +46,7 @@ public partial class InstalledTabItemViewModel : ViewModelBase
|
|||||||
|
|
||||||
private async Task ExecuteViewLocal(CancellationToken cancellationToken)
|
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}");
|
await _router.Navigate($"profile-editor/{profileId}");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public partial class LayoutSelectionStepViewModel : SubmissionViewModel
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ArtemisLayout layout = new(selected[0], LayoutSource.User);
|
ArtemisLayout layout = new(selected[0]);
|
||||||
if (!layout.IsValid)
|
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);
|
await _windowService.ShowConfirmContentDialog("Failed to load layout", "The selected file does not appear to be a valid RGB.NET layout file.", "Close", null);
|
||||||
|
|||||||
@ -5,11 +5,13 @@ using System.Threading.Tasks;
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Screens.Device;
|
using Artemis.UI.Screens.Device;
|
||||||
|
using Artemis.UI.Screens.Device.Layout;
|
||||||
using Artemis.UI.Services.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Services.MainWindow;
|
using Artemis.UI.Shared.Services.MainWindow;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using RGB.NET.Core;
|
using RGB.NET.Core;
|
||||||
|
using DeviceLogicalLayoutDialogViewModel = Artemis.UI.Screens.Device.Layout.DeviceLogicalLayoutDialogViewModel;
|
||||||
using KeyboardLayoutType = Artemis.Core.KeyboardLayoutType;
|
using KeyboardLayoutType = Artemis.Core.KeyboardLayoutType;
|
||||||
|
|
||||||
namespace Artemis.UI.Services;
|
namespace Artemis.UI.Services;
|
||||||
@ -61,7 +63,7 @@ public class DeviceLayoutService : IDeviceLayoutService
|
|||||||
|
|
||||||
await Task.Delay(400);
|
await Task.Delay(400);
|
||||||
_deviceService.SaveDevice(artemisDevice);
|
_deviceService.SaveDevice(artemisDevice);
|
||||||
_deviceService.ApplyDeviceLayout(artemisDevice, artemisDevice.GetBestDeviceLayout());
|
_deviceService.LoadDeviceLayout(artemisDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool DeviceNeedsLayout(ArtemisDevice d)
|
private bool DeviceNeedsLayout(ArtemisDevice d)
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Artemis.Core.Providers;
|
||||||
using Artemis.WebClient.Workshop.Extensions;
|
using Artemis.WebClient.Workshop.Extensions;
|
||||||
using Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
using Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
||||||
using Artemis.WebClient.Workshop.Handlers.UploadHandlers;
|
using Artemis.WebClient.Workshop.Handlers.UploadHandlers;
|
||||||
|
using Artemis.WebClient.Workshop.Providers;
|
||||||
using Artemis.WebClient.Workshop.Repositories;
|
using Artemis.WebClient.Workshop.Repositories;
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
using Artemis.WebClient.Workshop.State;
|
using Artemis.WebClient.Workshop.State;
|
||||||
@ -46,6 +48,7 @@ public static class ContainerExtensions
|
|||||||
container.Register<IAuthenticationRepository, AuthenticationRepository>(Reuse.Singleton);
|
container.Register<IAuthenticationRepository, AuthenticationRepository>(Reuse.Singleton);
|
||||||
container.Register<IAuthenticationService, AuthenticationService>(Reuse.Singleton);
|
container.Register<IAuthenticationService, AuthenticationService>(Reuse.Singleton);
|
||||||
container.Register<IWorkshopService, WorkshopService>(Reuse.Singleton);
|
container.Register<IWorkshopService, WorkshopService>(Reuse.Singleton);
|
||||||
|
container.Register<ILayoutProvider, WorkshopLayoutProvider>(Reuse.Singleton);
|
||||||
|
|
||||||
container.Register<EntryUploadHandlerFactory>(Reuse.Transient);
|
container.Register<EntryUploadHandlerFactory>(Reuse.Transient);
|
||||||
container.RegisterMany(workshopAssembly, type => type.IsAssignableTo<IEntryUploadHandler>(), Reuse.Transient);
|
container.RegisterMany(workshopAssembly, type => type.IsAssignableTo<IEntryUploadHandler>(), Reuse.Transient);
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
using Artemis.UI.Shared.Extensions;
|
using System.Data;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Shared.Extensions;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Utilities;
|
using Artemis.UI.Shared.Utilities;
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
|
||||||
@ -8,17 +13,17 @@ public class LayoutEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
{
|
{
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IWorkshopService _workshopService;
|
private readonly IWorkshopService _workshopService;
|
||||||
|
private readonly IDeviceService _deviceService;
|
||||||
|
|
||||||
public LayoutEntryInstallationHandler(IHttpClientFactory httpClientFactory, IWorkshopService workshopService)
|
public LayoutEntryInstallationHandler(IHttpClientFactory httpClientFactory, IWorkshopService workshopService, IDeviceService deviceService)
|
||||||
{
|
{
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
_workshopService = workshopService;
|
_workshopService = workshopService;
|
||||||
|
_deviceService = deviceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EntryInstallResult> InstallAsync(IGetEntryById_Entry entry, long releaseId, Progress<StreamProgress> progress, CancellationToken cancellationToken)
|
public async Task<EntryInstallResult> InstallAsync(IGetEntryById_Entry entry, long releaseId, Progress<StreamProgress> progress, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
|
||||||
|
|
||||||
using MemoryStream stream = new();
|
using MemoryStream stream = new();
|
||||||
|
|
||||||
// Download the provided release
|
// Download the provided release
|
||||||
@ -32,14 +37,45 @@ public class LayoutEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
return EntryInstallResult.FromFailure(e.Message);
|
return EntryInstallResult.FromFailure(e.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return EntryInstallResult.FromSuccess();
|
// Ensure there is an installed entry
|
||||||
|
InstalledEntry installedEntry = _workshopService.GetInstalledEntry(entry) ?? _workshopService.CreateInstalledEntry(entry);
|
||||||
|
DirectoryInfo entryDirectory = installedEntry.GetDirectory();
|
||||||
|
|
||||||
|
// If the folder already exists, remove it so that if the layout now contains less files, old things dont stick around
|
||||||
|
if (entryDirectory.Exists)
|
||||||
|
entryDirectory.Delete(true);
|
||||||
|
entryDirectory.Create();
|
||||||
|
|
||||||
|
// Extract the archive, we could go through the hoops of keeping track of progress but this should be so quick it doesn't matter
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
using ZipArchive archive = new(stream);
|
||||||
|
archive.ExtractToDirectory(entryDirectory.FullName);
|
||||||
|
|
||||||
|
ArtemisLayout layout = new(Path.Combine(entryDirectory.FullName, "layout.xml"));
|
||||||
|
if (layout.IsValid)
|
||||||
|
return EntryInstallResult.FromSuccess(layout);
|
||||||
|
|
||||||
|
// If the layout ended up being invalid yoink it out again, shoooo
|
||||||
|
entryDirectory.Delete(true);
|
||||||
|
_workshopService.RemoveInstalledEntry(installedEntry);
|
||||||
|
return EntryInstallResult.FromFailure("Layout failed to load because it is invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
public async Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
// Remove the layout from any devices currently using it
|
||||||
|
foreach (ArtemisDevice device in _deviceService.Devices)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
if (!Guid.TryParse(installedEntry.LocalReference, out Guid profileId))
|
// Remove from filesystem
|
||||||
return EntryUninstallResult.FromFailure("Local reference does not contain a GUID");
|
DirectoryInfo directory = installedEntry.GetDirectory(true);
|
||||||
|
if (directory.Exists)
|
||||||
|
directory.Delete();
|
||||||
|
|
||||||
|
// Remove entry
|
||||||
|
_workshopService.RemoveInstalledEntry(installedEntry);
|
||||||
|
|
||||||
|
return EntryUninstallResult.FromSuccess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,13 +36,13 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
|
|
||||||
// Find existing installation to potentially replace the profile
|
// Find existing installation to potentially replace the profile
|
||||||
InstalledEntry? installedEntry = _workshopService.GetInstalledEntry(entry);
|
InstalledEntry? installedEntry = _workshopService.GetInstalledEntry(entry);
|
||||||
if (installedEntry != null && Guid.TryParse(installedEntry.LocalReference, out Guid profileId))
|
if (installedEntry != null && installedEntry.TryGetMetadata("ProfileId", out Guid profileId))
|
||||||
{
|
{
|
||||||
ProfileConfiguration? existing = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(c => c.ProfileId == profileId);
|
ProfileConfiguration? existing = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).FirstOrDefault(c => c.ProfileId == profileId);
|
||||||
if (existing != null)
|
if (existing != null)
|
||||||
{
|
{
|
||||||
ProfileConfiguration overwritten = await _profileService.OverwriteProfile(stream, existing);
|
ProfileConfiguration overwritten = await _profileService.OverwriteProfile(stream, existing);
|
||||||
installedEntry.LocalReference = overwritten.ProfileId.ToString();
|
installedEntry.SetMetadata("ProfileId", overwritten.ProfileId);
|
||||||
|
|
||||||
// Update the release and return the profile configuration
|
// Update the release and return the profile configuration
|
||||||
UpdateRelease(releaseId, installedEntry);
|
UpdateRelease(releaseId, installedEntry);
|
||||||
@ -56,7 +56,7 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
// Add the profile as a fresh import
|
// Add the profile as a fresh import
|
||||||
ProfileCategory category = _profileService.ProfileCategories.FirstOrDefault(c => c.Name == "Workshop") ?? _profileService.CreateProfileCategory("Workshop", true);
|
ProfileCategory category = _profileService.ProfileCategories.FirstOrDefault(c => c.Name == "Workshop") ?? _profileService.CreateProfileCategory("Workshop", true);
|
||||||
ProfileConfiguration imported = await _profileService.ImportProfile(stream, category, true, true, null);
|
ProfileConfiguration imported = await _profileService.ImportProfile(stream, category, true, true, null);
|
||||||
installedEntry.LocalReference = imported.ProfileId.ToString();
|
installedEntry.SetMetadata("ProfileId", imported.ProfileId);
|
||||||
|
|
||||||
// Update the release and return the profile configuration
|
// Update the release and return the profile configuration
|
||||||
UpdateRelease(releaseId, installedEntry);
|
UpdateRelease(releaseId, installedEntry);
|
||||||
@ -65,7 +65,7 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
|||||||
|
|
||||||
public async Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
public async Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!Guid.TryParse(installedEntry.LocalReference, out Guid profileId))
|
if (!installedEntry.TryGetMetadata("ProfileId", out Guid profileId))
|
||||||
return EntryUninstallResult.FromFailure("Local reference does not contain a GUID");
|
return EntryUninstallResult.FromFailure("Local reference does not contain a GUID");
|
||||||
|
|
||||||
return await Task.Run(() =>
|
return await Task.Run(() =>
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Providers;
|
||||||
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
|
||||||
|
namespace Artemis.WebClient.Workshop.Providers;
|
||||||
|
|
||||||
|
public class WorkshopLayoutProvider : ILayoutProvider
|
||||||
|
{
|
||||||
|
public static string LayoutType = "Workshop";
|
||||||
|
|
||||||
|
private readonly IWorkshopService _workshopService;
|
||||||
|
|
||||||
|
public WorkshopLayoutProvider(IWorkshopService workshopService)
|
||||||
|
{
|
||||||
|
_workshopService = workshopService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ArtemisLayout? GetDeviceLayout(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
InstalledEntry? layoutEntry = _workshopService.GetInstalledEntries().FirstOrDefault(e => e.EntryType == EntryType.Layout && MatchesDevice(e, device));
|
||||||
|
if (layoutEntry == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string layoutPath = Path.Combine(Constants.WorkshopFolder, layoutEntry.EntryId.ToString(), "layout.xml");
|
||||||
|
if (!File.Exists(layoutPath))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return new ArtemisLayout(layoutPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void ApplyLayout(ArtemisDevice device, ArtemisLayout layout)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool IsMatch(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
return device.LayoutSelection.Type == LayoutType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool MatchesDevice(InstalledEntry entry, ArtemisDevice device)
|
||||||
|
{
|
||||||
|
return entry.TryGetMetadata("DeviceId", out HashSet<string>? deviceIds) && deviceIds.Contains(device.Identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,13 +1,16 @@
|
|||||||
using Artemis.Storage.Entities.Workshop;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Storage.Entities.Workshop;
|
||||||
|
|
||||||
namespace Artemis.WebClient.Workshop.Services;
|
namespace Artemis.WebClient.Workshop.Services;
|
||||||
|
|
||||||
public class InstalledEntry
|
public class InstalledEntry
|
||||||
{
|
{
|
||||||
|
private Dictionary<string, object> _metadata = new();
|
||||||
|
|
||||||
internal InstalledEntry(EntryEntity entity)
|
internal InstalledEntry(EntryEntity entity)
|
||||||
{
|
{
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,8 +35,6 @@ public class InstalledEntry
|
|||||||
public string ReleaseVersion { get; set; } = string.Empty;
|
public string ReleaseVersion { get; set; } = string.Empty;
|
||||||
public DateTimeOffset InstalledAt { get; set; }
|
public DateTimeOffset InstalledAt { get; set; }
|
||||||
|
|
||||||
public string? LocalReference { get; set; }
|
|
||||||
|
|
||||||
internal EntryEntity Entity { get; }
|
internal EntryEntity Entity { get; }
|
||||||
|
|
||||||
internal void Load()
|
internal void Load()
|
||||||
@ -48,7 +49,7 @@ public class InstalledEntry
|
|||||||
ReleaseVersion = Entity.ReleaseVersion;
|
ReleaseVersion = Entity.ReleaseVersion;
|
||||||
InstalledAt = Entity.InstalledAt;
|
InstalledAt = Entity.InstalledAt;
|
||||||
|
|
||||||
LocalReference = Entity.LocalReference;
|
_metadata = new Dictionary<string, object>(Entity.Metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Save()
|
internal void Save()
|
||||||
@ -63,6 +64,60 @@ public class InstalledEntry
|
|||||||
Entity.ReleaseVersion = ReleaseVersion;
|
Entity.ReleaseVersion = ReleaseVersion;
|
||||||
Entity.InstalledAt = InstalledAt;
|
Entity.InstalledAt = InstalledAt;
|
||||||
|
|
||||||
Entity.LocalReference = LocalReference;
|
Entity.Metadata = new Dictionary<string, object>(_metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the metadata value associated with the specified key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key of the value to get.</param>
|
||||||
|
/// <param name="value">When this method returns, contains the value associated with the specified key, if the key is found and of type <typeparamref name="T"/>;
|
||||||
|
/// otherwise, the default value for the type of the value parameter. This parameter is passed uninitialized.</param>
|
||||||
|
/// <typeparam name="T">The type of the value.</typeparam>
|
||||||
|
/// <returns><see langword="true"/> if the metadata contains an element with the specified key; otherwise, <see langword="false"/>.</returns>
|
||||||
|
public bool TryGetMetadata<T>(string key, [NotNullWhen(true)] out T? value)
|
||||||
|
{
|
||||||
|
if (!_metadata.TryGetValue(key, out object? objectValue) || objectValue is not T result)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets metadata with the provided key to the provided value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key of the value to set</param>
|
||||||
|
/// <param name="value">The value to set.</param>
|
||||||
|
public void SetMetadata(string key, object value)
|
||||||
|
{
|
||||||
|
_metadata.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes metadata with the provided key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key of the metadata to remove</param>
|
||||||
|
/// <returns><see langword="true"/> if the element is successfully found and removed; otherwise, <see langword="false"/>.</returns>
|
||||||
|
public bool RemoveMetadata(string key)
|
||||||
|
{
|
||||||
|
return _metadata.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the directory info of the entry, where any files would be stored if applicable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rootDirectory">A value indicating whether or not to return the root directory of the entry, and not the version.</param>
|
||||||
|
/// <returns>The directory info of the entry, where any files would be stored if applicable.</returns>
|
||||||
|
public DirectoryInfo GetDirectory(bool rootDirectory = false)
|
||||||
|
{
|
||||||
|
if (rootDirectory)
|
||||||
|
return new DirectoryInfo(Path.Combine(Constants.WorkshopFolder, EntryId.ToString()));
|
||||||
|
|
||||||
|
string safeVersion = Path.GetInvalidFileNameChars().Aggregate(ReleaseVersion, (current, c) => current.Replace(c, '-'));
|
||||||
|
return new DirectoryInfo(Path.Combine(Constants.WorkshopFolder, EntryId.ToString(), safeVersion));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user