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

Merge branch 'development'

This commit is contained in:
Robert 2021-05-15 22:43:00 +02:00
commit 195401fa8f
31 changed files with 996 additions and 699 deletions

View File

@ -48,7 +48,7 @@ namespace Artemis.Core
public void Apply(Layer layer, List<ArtemisDevice> devices) public void Apply(Layer layer, List<ArtemisDevice> devices)
{ {
IEnumerable<ArtemisDevice> matches = devices IEnumerable<ArtemisDevice> matches = devices
.Where(d => d.RgbDevice.DeviceInfo.DeviceType == DeviceType) .Where(d => DeviceType == RGBDeviceType.All || d.RgbDevice.DeviceInfo.DeviceType == DeviceType)
.OrderBy(d => d.Rectangle.Top) .OrderBy(d => d.Rectangle.Top)
.ThenBy(d => d.Rectangle.Left) .ThenBy(d => d.Rectangle.Left)
.Skip(Skip); .Skip(Skip);

View File

@ -66,8 +66,8 @@ namespace Artemis.Core
_leds = new List<ArtemisLed>(); _leds = new List<ArtemisLed>();
Load();
Adapter = new LayerAdapter(this); Adapter = new LayerAdapter(this);
Load();
Initialize(); Initialize();
} }
@ -242,6 +242,7 @@ namespace Artemis.Core
ExpandedPropertyGroups.AddRange(LayerEntity.ExpandedPropertyGroups); ExpandedPropertyGroups.AddRange(LayerEntity.ExpandedPropertyGroups);
LoadRenderElement(); LoadRenderElement();
Adapter.Load();
} }
internal override void Save() internal override void Save()
@ -276,6 +277,9 @@ namespace Artemis.Core
LayerEntity.Leds.Add(ledEntity); LayerEntity.Leds.Add(ledEntity);
} }
// Adaption hints
Adapter.Save();
SaveRenderElement(); SaveRenderElement();
} }

View File

@ -70,33 +70,42 @@ namespace Artemis.Core
public List<IAdaptionHint> DetermineHints(IEnumerable<ArtemisDevice> devices) public List<IAdaptionHint> DetermineHints(IEnumerable<ArtemisDevice> devices)
{ {
List<IAdaptionHint> newHints = new(); List<IAdaptionHint> newHints = new();
// Any fully covered device will add a device adaption hint for that type if (devices.All(DoesLayerCoverDevice))
foreach (IGrouping<ArtemisDevice, ArtemisLed> deviceLeds in Layer.Leds.GroupBy(l => l.Device))
{ {
ArtemisDevice device = deviceLeds.Key; DeviceAdaptionHint hint = new() {DeviceType = RGBDeviceType.All};
// If there is already an adaption hint for this type, don't add another AdaptionHints.Add(hint);
if (AdaptionHints.Any(h => h is DeviceAdaptionHint d && d.DeviceType == device.RgbDevice.DeviceInfo.DeviceType)) newHints.Add(hint);
continue;
if (DoesLayerCoverDevice(device))
{
DeviceAdaptionHint hint = new() {DeviceType = device.RgbDevice.DeviceInfo.DeviceType};
AdaptionHints.Add(hint);
newHints.Add(hint);
}
} }
else
// Any fully covered category will add a category adaption hint for its category
foreach (DeviceCategory deviceCategory in Enum.GetValues<DeviceCategory>())
{ {
if (AdaptionHints.Any(h => h is CategoryAdaptionHint c && c.Category == deviceCategory)) // Any fully covered device will add a device adaption hint for that type
continue; foreach (IGrouping<ArtemisDevice, ArtemisLed> deviceLeds in Layer.Leds.GroupBy(l => l.Device))
List<ArtemisDevice> categoryDevices = devices.Where(d => d.Categories.Contains(deviceCategory)).ToList();
if (categoryDevices.Any() && categoryDevices.All(DoesLayerCoverDevice))
{ {
CategoryAdaptionHint hint = new() {Category = deviceCategory}; ArtemisDevice device = deviceLeds.Key;
AdaptionHints.Add(hint); // If there is already an adaption hint for this type, don't add another
newHints.Add(hint); if (AdaptionHints.Any(h => h is DeviceAdaptionHint d && d.DeviceType == device.RgbDevice.DeviceInfo.DeviceType))
continue;
if (DoesLayerCoverDevice(device))
{
DeviceAdaptionHint hint = new() {DeviceType = device.RgbDevice.DeviceInfo.DeviceType};
AdaptionHints.Add(hint);
newHints.Add(hint);
}
}
// Any fully covered category will add a category adaption hint for its category
foreach (DeviceCategory deviceCategory in Enum.GetValues<DeviceCategory>())
{
if (AdaptionHints.Any(h => h is CategoryAdaptionHint c && c.Category == deviceCategory))
continue;
List<ArtemisDevice> categoryDevices = devices.Where(d => d.Categories.Contains(deviceCategory)).ToList();
if (categoryDevices.Any() && categoryDevices.All(DoesLayerCoverDevice))
{
CategoryAdaptionHint hint = new() {Category = deviceCategory};
AdaptionHints.Add(hint);
newHints.Add(hint);
}
} }
} }

View File

@ -14,6 +14,7 @@ namespace Artemis.Core
{ {
private readonly object _lock = new(); private readonly object _lock = new();
private bool _isActivated; private bool _isActivated;
private bool _isFreshImport;
internal Profile(ProfileModule module, string name) : base(null!) internal Profile(ProfileModule module, string name) : base(null!)
{ {
@ -57,6 +58,20 @@ namespace Artemis.Core
private set => SetAndNotify(ref _isActivated, value); private set => SetAndNotify(ref _isActivated, value);
} }
/// <summary>
/// Gets or sets a boolean indicating whether this profile is freshly imported i.e. no changes have been made to it
/// since import
/// <para>
/// Note: As long as this is <see langword="true" />, profile adaption will be performed on load and any surface
/// changes
/// </para>
/// </summary>
public bool IsFreshImport
{
get => _isFreshImport;
set => SetAndNotify(ref _isFreshImport, value);
}
/// <summary> /// <summary>
/// Gets the profile entity this profile uses for persistent storage /// Gets the profile entity this profile uses for persistent storage
/// </summary> /// </summary>
@ -134,6 +149,16 @@ namespace Artemis.Core
layer.PopulateLeds(devices); layer.PopulateLeds(devices);
} }
/// <summary>
/// Occurs when the profile has been activated.
/// </summary>
public event EventHandler? Activated;
/// <summary>
/// Occurs when the profile is being deactivated.
/// </summary>
public event EventHandler? Deactivated;
/// <inheritdoc /> /// <inheritdoc />
protected override void Dispose(bool disposing) protected override void Dispose(bool disposing)
{ {
@ -156,6 +181,7 @@ namespace Artemis.Core
throw new ObjectDisposedException("Profile"); throw new ObjectDisposedException("Profile");
Name = ProfileEntity.Name; Name = ProfileEntity.Name;
IsFreshImport = ProfileEntity.IsFreshImport;
lock (ChildrenList) lock (ChildrenList)
{ {
@ -171,9 +197,7 @@ namespace Artemis.Core
Folder _ = new(this, "Root folder"); Folder _ = new(this, "Root folder");
} }
else else
{
AddChild(new Folder(this, this, rootFolder)); AddChild(new Folder(this, this, rootFolder));
}
} }
} }
@ -186,6 +210,7 @@ namespace Artemis.Core
ProfileEntity.ModuleId = Module.Id; ProfileEntity.ModuleId = Module.Id;
ProfileEntity.Name = Name; ProfileEntity.Name = Name;
ProfileEntity.IsActive = IsActivated; ProfileEntity.IsActive = IsActivated;
ProfileEntity.IsFreshImport = IsFreshImport;
foreach (ProfileElement profileElement in Children) foreach (ProfileElement profileElement in Children)
profileElement.Save(); profileElement.Save();
@ -212,18 +237,6 @@ namespace Artemis.Core
} }
} }
#region Events
/// <summary>
/// Occurs when the profile has been activated.
/// </summary>
public event EventHandler? Activated;
/// <summary>
/// Occurs when the profile is being deactivated.
/// </summary>
public event EventHandler? Deactivated;
private void OnActivated() private void OnActivated()
{ {
Activated?.Invoke(this, EventArgs.Empty); Activated?.Invoke(this, EventArgs.Empty);
@ -233,7 +246,5 @@ namespace Artemis.Core
{ {
Deactivated?.Invoke(this, EventArgs.Empty); Deactivated?.Invoke(this, EventArgs.Empty);
} }
#endregion
} }
} }

View File

@ -37,6 +37,5 @@ namespace Artemis.Core
/// Gets a boolean indicating whether this was the last active profile /// Gets a boolean indicating whether this was the last active profile
/// </summary> /// </summary>
public bool IsLastActiveProfile { get; } public bool IsLastActiveProfile { get; }
} }
} }

View File

@ -381,7 +381,8 @@ namespace Artemis.Core
"set to true because the device provider does not support it"); "set to true because the device provider does not support it");
if (layout.IsValid) if (layout.IsValid)
layout.RgbLayout!.ApplyTo(RgbDevice, createMissingLeds, removeExcessiveLeds); layout.ApplyTo(RgbDevice, createMissingLeds, removeExcessiveLeds);
UpdateLeds(); UpdateLeds();

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using RGB.NET.Core;
using RGB.NET.Layout; using RGB.NET.Layout;
namespace Artemis.Core namespace Artemis.Core
@ -65,6 +66,44 @@ namespace Artemis.Core
/// </summary> /// </summary>
public LayoutCustomDeviceData LayoutCustomDeviceData { get; private set; } = null!; public LayoutCustomDeviceData LayoutCustomDeviceData { get; private set; } = null!;
/// <summary>
/// Applies the layout to the provided device
/// </summary>
public void ApplyTo(IRGBDevice device, bool createMissingLeds = false, bool removeExcessiveLeds = false)
{
device.Size = new Size(MathF.Round(RgbLayout.Width), MathF.Round(RgbLayout.Height));
device.DeviceInfo.LayoutMetadata = RgbLayout.CustomData;
HashSet<LedId> ledIds = new();
foreach (ILedLayout layoutLed in RgbLayout.Leds)
{
if (Enum.TryParse(layoutLed.Id, true, out LedId ledId))
{
ledIds.Add(ledId);
Led? led = device[ledId];
if (led == null && createMissingLeds)
led = device.AddLed(ledId, new Point(), new Size());
if (led != null)
{
led.Location = new Point(MathF.Round(layoutLed.X), MathF.Round(layoutLed.Y));
led.Size = new Size(MathF.Round(layoutLed.Width), MathF.Round(layoutLed.Height));
led.Shape = layoutLed.Shape;
led.ShapeData = layoutLed.ShapeData;
led.LayoutMetadata = layoutLed.CustomData;
}
}
}
if (removeExcessiveLeds)
{
List<LedId> ledsToRemove = device.Select(led => led.Id).Where(id => !ledIds.Contains(id)).ToList();
foreach (LedId led in ledsToRemove)
device.RemoveLed(led);
}
}
internal void ApplyDevice(ArtemisDevice artemisDevice) internal void ApplyDevice(ArtemisDevice artemisDevice)
{ {
Device = artemisDevice; Device = artemisDevice;

View File

@ -1,11 +1,15 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core.DataModelExpansions; using Artemis.Core.DataModelExpansions;
using Artemis.Core.Services;
using Artemis.Storage.Entities.Profile;
using Newtonsoft.Json;
using SkiaSharp; using SkiaSharp;
namespace Artemis.Core.Modules namespace Artemis.Core.Modules
@ -91,11 +95,16 @@ namespace Artemis.Core.Modules
/// </summary> /// </summary>
public abstract class ProfileModule : Module public abstract class ProfileModule : Module
{ {
private readonly List<string> _defaultProfilePaths = new();
private readonly List<string> _pendingDefaultProfilePaths = new();
private readonly List<ProfileEntity> _defaultProfiles = new();
private readonly object _lock = new();
/// <summary> /// <summary>
/// Gets a list of all properties ignored at runtime using <c>IgnoreProperty(x => x.y)</c> /// Gets a list of all properties ignored at runtime using <c>IgnoreProperty(x => x.y)</c>
/// </summary> /// </summary>
protected internal readonly List<PropertyInfo> HiddenPropertiesList = new(); protected internal readonly List<PropertyInfo> HiddenPropertiesList = new();
private readonly object _lock = new();
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ProfileModule" /> class /// Creates a new instance of the <see cref="ProfileModule" /> class
@ -130,6 +139,11 @@ namespace Artemis.Core.Modules
/// </summary> /// </summary>
public bool AnimatingProfileChange { get; private set; } public bool AnimatingProfileChange { get; private set; }
/// <summary>
/// Gets a list of default profiles, to add a new default profile use <see cref="AddDefaultProfile" />
/// </summary>
internal ReadOnlyCollection<ProfileEntity> DefaultProfiles => _defaultProfiles.AsReadOnly();
/// <summary> /// <summary>
/// Called after the profile has updated /// Called after the profile has updated
/// </summary> /// </summary>
@ -148,6 +162,71 @@ namespace Artemis.Core.Modules
{ {
} }
/// <summary>
/// Occurs when the <see cref="ActiveProfile" /> has changed
/// </summary>
public event EventHandler? ActiveProfileChanged;
/// <summary>
/// Adds a default profile by reading it from the file found at the provided path
/// </summary>
/// <param name="file">A path pointing towards a profile file. May be relative to the plugin directory.</param>
/// <returns>
/// <see langword="true" /> if the default profile was added; <see langword="false" /> if it was not because it is
/// already in the list.
/// </returns>
protected bool AddDefaultProfile(string file)
{
// It can be null if the plugin has not loaded yet...
if (Plugin == null!)
{
if (_pendingDefaultProfilePaths.Contains(file))
return false;
_pendingDefaultProfilePaths.Add(file);
return true;
}
if (!Path.IsPathRooted(file))
file = Plugin.ResolveRelativePath(file);
if (_defaultProfilePaths.Contains(file))
return false;
_defaultProfilePaths.Add(file);
// Ensure the file exists
if (!File.Exists(file))
throw new ArtemisPluginFeatureException(this, $"Could not find default profile at {file}.");
// Deserialize and make sure that succeeded
ProfileEntity? profileEntity = JsonConvert.DeserializeObject<ProfileEntity>(File.ReadAllText(file), ProfileService.ExportSettings);
if (profileEntity == null)
throw new ArtemisPluginFeatureException(this, $"Failed to deserialize default profile at {file}.");
// Ensure the profile ID is unique
if (_defaultProfiles.Any(d => d.Id == profileEntity.Id))
throw new ArtemisPluginFeatureException(this, $"Cannot add default profile from {file}, profile ID {profileEntity.Id} already in use.");
profileEntity.IsFreshImport = true;
_defaultProfiles.Add(profileEntity);
return true;
}
/// <summary>
/// Invokes the <see cref="ActiveProfileChanged" /> event
/// </summary>
protected virtual void OnActiveProfileChanged()
{
ActiveProfileChanged?.Invoke(this, EventArgs.Empty);
}
internal override void InternalEnable()
{
foreach (string pendingDefaultProfile in _pendingDefaultProfilePaths)
AddDefaultProfile(pendingDefaultProfile);
_pendingDefaultProfilePaths.Clear();
base.InternalEnable();
}
internal override void InternalUpdate(double deltaTime) internal override void InternalUpdate(double deltaTime)
{ {
StartUpdateMeasure(); StartUpdateMeasure();
@ -245,22 +324,5 @@ namespace Artemis.Core.Modules
base.Deactivate(isDeactivateOverride); base.Deactivate(isDeactivateOverride);
Activate(isActivateOverride); Activate(isActivateOverride);
} }
#region Events
/// <summary>
/// Occurs when the <see cref="ActiveProfile" /> has changed
/// </summary>
public event EventHandler? ActiveProfileChanged;
/// <summary>
/// Invokes the <see cref="ActiveProfileChanged" /> event
/// </summary>
protected virtual void OnActiveProfileChanged()
{
ActiveProfileChanged?.Invoke(this, EventArgs.Empty);
}
#endregion
} }
} }

View File

@ -23,7 +23,7 @@ namespace Artemis.Core
public abstract string Description { get; } public abstract string Description { get; }
/// <summary> /// <summary>
/// Gets a boolean indicating whether installing or uninstalling this prerequisite requires admin privileges /// [NYI] Gets a boolean indicating whether installing or uninstalling this prerequisite requires admin privileges
/// </summary> /// </summary>
public abstract bool RequiresElevation { get; } public abstract bool RequiresElevation { get; }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -17,11 +18,13 @@ namespace Artemis.Core
/// <param name="fileName">The target file to execute</param> /// <param name="fileName">The target file to execute</param>
/// <param name="arguments">A set of command-line arguments to use when starting the application</param> /// <param name="arguments">A set of command-line arguments to use when starting the application</param>
/// <param name="waitForExit">A boolean indicating whether the action should wait for the process to exit</param> /// <param name="waitForExit">A boolean indicating whether the action should wait for the process to exit</param>
public ExecuteFileAction(string name, string fileName, string? arguments = null, bool waitForExit = true) : base(name) /// <param name="elevate">A boolean indicating whether the file should run with administrator privileges (does not require <see cref="PluginPrerequisite.RequiresElevation"/>)</param>
public ExecuteFileAction(string name, string fileName, string? arguments = null, bool waitForExit = true, bool elevate = false) : base(name)
{ {
FileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); FileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
Arguments = arguments; Arguments = arguments;
WaitForExit = waitForExit; WaitForExit = waitForExit;
Elevate = elevate;
} }
/// <summary> /// <summary>
@ -30,7 +33,7 @@ namespace Artemis.Core
public string FileName { get; } public string FileName { get; }
/// <summary> /// <summary>
/// Gets a set of command-line arguments to use when starting the application /// Gets a set of command-line arguments to use when starting the application
/// </summary> /// </summary>
public string? Arguments { get; } public string? Arguments { get; }
@ -39,6 +42,11 @@ namespace Artemis.Core
/// </summary> /// </summary>
public bool WaitForExit { get; } public bool WaitForExit { get; }
/// <summary>
/// Gets a boolean indicating whether the file should run with administrator privileges
/// </summary>
public bool Elevate { get; }
/// <inheritdoc /> /// <inheritdoc />
public override async Task Execute(CancellationToken cancellationToken) public override async Task Execute(CancellationToken cancellationToken)
{ {
@ -48,7 +56,7 @@ namespace Artemis.Core
ShowProgressBar = true; ShowProgressBar = true;
ProgressIndeterminate = true; ProgressIndeterminate = true;
int result = await RunProcessAsync(FileName, Arguments); int result = await RunProcessAsync(FileName, Arguments, Elevate);
Status = $"{FileName} exited with code {result}"; Status = $"{FileName} exited with code {result}";
} }
@ -64,13 +72,19 @@ namespace Artemis.Core
} }
} }
private static Task<int> RunProcessAsync(string fileName, string? arguments) private static Task<int> RunProcessAsync(string fileName, string? arguments, bool elevate)
{ {
TaskCompletionSource<int> tcs = new(); TaskCompletionSource<int> tcs = new();
Process process = new() Process process = new()
{ {
StartInfo = {FileName = fileName, Arguments = arguments!}, StartInfo =
{
FileName = fileName,
Arguments = arguments!,
Verb = elevate ? "RunAs" : "",
UseShellExecute = elevate
},
EnableRaisingEvents = true EnableRaisingEvents = true
}; };
@ -80,7 +94,17 @@ namespace Artemis.Core
process.Dispose(); process.Dispose();
}; };
process.Start(); try
{
process.Start();
}
catch (Win32Exception e)
{
if (!elevate || e.NativeErrorCode != 0x4c7)
throw;
tcs.SetResult(-1);
}
return tcs.Task; return tcs.Task;
} }

View File

@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers; using System.Timers;
using Artemis.Core.Modules; using Artemis.Core.Modules;
using Artemis.Storage.Entities.Profile;
using Artemis.Storage.Repositories.Interfaces; using Artemis.Storage.Repositories.Interfaces;
using Serilog; using Serilog;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
@ -17,13 +18,15 @@ namespace Artemis.Core.Services
private static readonly SemaphoreSlim ActiveModuleSemaphore = new(1, 1); private static readonly SemaphoreSlim ActiveModuleSemaphore = new(1, 1);
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IModuleRepository _moduleRepository; private readonly IModuleRepository _moduleRepository;
private readonly IProfileRepository _profileRepository;
private readonly IPluginManagementService _pluginManagementService; private readonly IPluginManagementService _pluginManagementService;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
public ModuleService(ILogger logger, IModuleRepository moduleRepository, IPluginManagementService pluginManagementService, IProfileService profileService) public ModuleService(ILogger logger, IModuleRepository moduleRepository, IProfileRepository profileRepository, IPluginManagementService pluginManagementService, IProfileService profileService)
{ {
_logger = logger; _logger = logger;
_moduleRepository = moduleRepository; _moduleRepository = moduleRepository;
_profileRepository = profileRepository;
_pluginManagementService = pluginManagementService; _pluginManagementService = pluginManagementService;
_profileService = profileService; _profileService = profileService;
_pluginManagementService.PluginFeatureEnabled += OnPluginFeatureEnabled; _pluginManagementService.PluginFeatureEnabled += OnPluginFeatureEnabled;
@ -45,12 +48,24 @@ namespace Artemis.Core.Services
{ {
try try
{ {
ProfileModule? profileModule = module as ProfileModule;
if (profileModule != null && profileModule.DefaultProfiles.Any())
{
List<ProfileDescriptor> descriptors = _profileService.GetProfileDescriptors(profileModule);
foreach (ProfileEntity defaultProfile in profileModule.DefaultProfiles)
{
if (descriptors.All(d => d.Id != defaultProfile.Id))
_profileRepository.Add(defaultProfile);
}
}
module.Activate(false); module.Activate(false);
try try
{ {
// If this is a profile module, activate the last active profile after module activation // If this is a profile module, activate the last active profile after module activation
if (module is ProfileModule profileModule) if (profileModule != null)
await _profileService.ActivateLastProfileAnimated(profileModule); await _profileService.ActivateLastProfileAnimated(profileModule);
} }
catch (Exception e) catch (Exception e)

View File

@ -32,8 +32,8 @@ namespace Artemis.Core.Services
_rgbService.LedsChanged += RgbServiceOnLedsChanged; _rgbService.LedsChanged += RgbServiceOnLedsChanged;
} }
public JsonSerializerSettings MementoSettings { get; set; } = new() {TypeNameHandling = TypeNameHandling.All}; public static JsonSerializerSettings MementoSettings { get; set; } = new() {TypeNameHandling = TypeNameHandling.All};
public JsonSerializerSettings ExportSettings { get; set; } = new() {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented}; public static JsonSerializerSettings ExportSettings { get; set; } = new() {TypeNameHandling = TypeNameHandling.All, Formatting = Formatting.Indented};
public ProfileDescriptor? GetLastActiveProfile(ProfileModule module) public ProfileDescriptor? GetLastActiveProfile(ProfileModule module)
{ {
@ -64,8 +64,16 @@ namespace Artemis.Core.Services
private void ActiveProfilesPopulateLeds() private void ActiveProfilesPopulateLeds()
{ {
List<ProfileModule> profileModules = _pluginManagementService.GetFeaturesOfType<ProfileModule>(); List<ProfileModule> profileModules = _pluginManagementService.GetFeaturesOfType<ProfileModule>();
foreach (ProfileModule profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList()) foreach (ProfileModule profileModule in profileModules)
profileModule.ActiveProfile?.PopulateLeds(_rgbService.EnabledDevices); // Avoid race condition {
// Avoid race condition, make the check here
if (profileModule.ActiveProfile != null)
{
profileModule.ActiveProfile.PopulateLeds(_rgbService.EnabledDevices);
_logger.Debug("Profile is a fresh import, adapting to surface - {profile}", profileModule.ActiveProfile);
AdaptProfile(profileModule.ActiveProfile);
}
}
} }
public List<ProfileDescriptor> GetProfileDescriptors(ProfileModule module) public List<ProfileDescriptor> GetProfileDescriptors(ProfileModule module)
@ -109,6 +117,12 @@ namespace Artemis.Core.Services
InstantiateProfile(profile); InstantiateProfile(profile);
profileDescriptor.ProfileModule.ChangeActiveProfile(profile, _rgbService.EnabledDevices); profileDescriptor.ProfileModule.ChangeActiveProfile(profile, _rgbService.EnabledDevices);
if (profile.IsFreshImport)
{
_logger.Debug("Profile is a fresh import, adapting to surface - {profile}", profile);
AdaptProfile(profile);
}
SaveActiveProfile(profileDescriptor.ProfileModule); SaveActiveProfile(profileDescriptor.ProfileModule);
return profile; return profile;
@ -156,6 +170,12 @@ namespace Artemis.Core.Services
_rgbService.LedsChanged += ActivatingRgbServiceOnLedsChanged; _rgbService.LedsChanged += ActivatingRgbServiceOnLedsChanged;
await profileDescriptor.ProfileModule.ChangeActiveProfileAnimated(profile, _rgbService.EnabledDevices); await profileDescriptor.ProfileModule.ChangeActiveProfileAnimated(profile, _rgbService.EnabledDevices);
if (profile.IsFreshImport)
{
_logger.Debug("Profile is a fresh import, adapting to surface - {profile}", profile);
AdaptProfile(profile);
}
SaveActiveProfile(profileDescriptor.ProfileModule); SaveActiveProfile(profileDescriptor.ProfileModule);
_pluginManagementService.PluginEnabled -= ActivatingProfilePluginToggle; _pluginManagementService.PluginEnabled -= ActivatingProfilePluginToggle;
@ -193,6 +213,8 @@ namespace Artemis.Core.Services
public void DeleteProfile(ProfileDescriptor profileDescriptor) public void DeleteProfile(ProfileDescriptor profileDescriptor)
{ {
ProfileEntity profileEntity = _profileRepository.Get(profileDescriptor.Id); ProfileEntity profileEntity = _profileRepository.Get(profileDescriptor.Id);
if (profileEntity == null)
return;
_profileRepository.Remove(profileEntity); _profileRepository.Remove(profileEntity);
} }
@ -203,6 +225,7 @@ namespace Artemis.Core.Services
profile.RedoStack.Clear(); profile.RedoStack.Clear();
profile.UndoStack.Push(memento); profile.UndoStack.Push(memento);
profile.IsFreshImport = false;
profile.Save(); profile.Save();
if (includeChildren) if (includeChildren)
{ {
@ -289,6 +312,7 @@ namespace Artemis.Core.Services
profileEntity.UpdateGuid(Guid.NewGuid()); profileEntity.UpdateGuid(Guid.NewGuid());
profileEntity.Name = $"{profileEntity.Name} - {nameAffix}"; profileEntity.Name = $"{profileEntity.Name} - {nameAffix}";
profileEntity.IsFreshImport = true;
_profileRepository.Add(profileEntity); _profileRepository.Add(profileEntity);
return new ProfileDescriptor(profileModule, profileEntity); return new ProfileDescriptor(profileModule, profileEntity);
} }

View File

@ -17,6 +17,7 @@ namespace Artemis.Storage.Entities.Profile
public string Name { get; set; } public string Name { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
public bool IsFreshImport { get; set; }
public List<FolderEntity> Folders { get; set; } public List<FolderEntity> Folders { get; set; }
public List<LayerEntity> Layers { get; set; } public List<LayerEntity> Layers { get; set; }

View File

@ -17,7 +17,7 @@ namespace Artemis.UI.Shared.Services
/// Sets up the notification provider that shows desktop notifications /// Sets up the notification provider that shows desktop notifications
/// </summary> /// </summary>
/// <param name="notificationProvider">The notification provider that shows desktop notifications</param> /// <param name="notificationProvider">The notification provider that shows desktop notifications</param>
void ConfigureNotificationProvider(INotificationProvider notificationProvider); void SetNotificationProvider(INotificationProvider notificationProvider);
/// <summary> /// <summary>
/// Queues a notification message for display in a snackbar. /// Queues a notification message for display in a snackbar.
@ -123,7 +123,9 @@ namespace Artemis.UI.Shared.Services
/// </summary> /// </summary>
/// <param name="title">The title of the notification</param> /// <param name="title">The title of the notification</param>
/// <param name="message">The message of the notification</param> /// <param name="message">The message of the notification</param>
void ShowNotification(string title, string message); /// <param name="activatedCallback">An optional callback that is invoked when the notification is clicked</param>
/// <param name="dismissedCallback">An optional callback that is invoked when the notification is dismissed</param>
void ShowNotification(string title, string message, Action? activatedCallback = null, Action? dismissedCallback = null);
/// <summary> /// <summary>
/// Shows a desktop notification with a Material Design icon /// Shows a desktop notification with a Material Design icon
@ -131,7 +133,9 @@ namespace Artemis.UI.Shared.Services
/// <param name="title">The title of the notification</param> /// <param name="title">The title of the notification</param>
/// <param name="message">The message of the notification</param> /// <param name="message">The message of the notification</param>
/// <param name="icon">The name of the icon</param> /// <param name="icon">The name of the icon</param>
void ShowNotification(string title, string message, PackIconKind icon); /// <param name="activatedCallback">An optional callback that is invoked when the notification is clicked</param>
/// <param name="dismissedCallback">An optional callback that is invoked when the notification is dismissed</param>
void ShowNotification(string title, string message, PackIconKind icon, Action? activatedCallback = null, Action? dismissedCallback = null);
/// <summary> /// <summary>
/// Shows a desktop notification with a Material Design icon /// Shows a desktop notification with a Material Design icon
@ -139,6 +143,8 @@ namespace Artemis.UI.Shared.Services
/// <param name="title">The title of the notification</param> /// <param name="title">The title of the notification</param>
/// <param name="message">The message of the notification</param> /// <param name="message">The message of the notification</param>
/// <param name="icon">The name of the icon as a string</param> /// <param name="icon">The name of the icon as a string</param>
void ShowNotification(string title, string message, string icon); /// <param name="activatedCallback">An optional callback that is invoked when the notification is clicked</param>
/// <param name="dismissedCallback">An optional callback that is invoked when the notification is dismissed</param>
void ShowNotification(string title, string message, string icon, Action? activatedCallback = null, Action? dismissedCallback = null);
} }
} }

View File

@ -1,4 +1,5 @@
using MaterialDesignThemes.Wpf; using System;
using MaterialDesignThemes.Wpf;
namespace Artemis.UI.Shared.Services namespace Artemis.UI.Shared.Services
{ {
@ -6,7 +7,7 @@ namespace Artemis.UI.Shared.Services
/// Represents a class provides desktop notifications so that <see cref="IMessageService" /> can us it to show desktop /// Represents a class provides desktop notifications so that <see cref="IMessageService" /> can us it to show desktop
/// notifications /// notifications
/// </summary> /// </summary>
public interface INotificationProvider public interface INotificationProvider : IDisposable
{ {
/// <summary> /// <summary>
/// Shows a notification /// Shows a notification
@ -14,6 +15,8 @@ namespace Artemis.UI.Shared.Services
/// <param name="title">The title of the notification</param> /// <param name="title">The title of the notification</param>
/// <param name="message">The message of the notification</param> /// <param name="message">The message of the notification</param>
/// <param name="icon">The Material Design icon to show in the notification</param> /// <param name="icon">The Material Design icon to show in the notification</param>
void ShowNotification(string title, string message, PackIconKind icon); /// <param name="activatedCallback">A callback that is invoked when the notification is clicked</param>
/// <param name="dismissedCallback">A callback that is invoked when the notification is dismissed</param>
void ShowNotification(string title, string message, PackIconKind icon, Action? activatedCallback, Action? dismissedCallback);
} }
} }

View File

@ -3,7 +3,7 @@ using MaterialDesignThemes.Wpf;
namespace Artemis.UI.Shared.Services namespace Artemis.UI.Shared.Services
{ {
internal class MessageService : IMessageService internal class MessageService : IMessageService, IDisposable
{ {
private INotificationProvider? _notificationProvider; private INotificationProvider? _notificationProvider;
public ISnackbarMessageQueue MainMessageQueue { get; } public ISnackbarMessageQueue MainMessageQueue { get; }
@ -14,8 +14,12 @@ namespace Artemis.UI.Shared.Services
} }
/// <inheritdoc /> /// <inheritdoc />
public void ConfigureNotificationProvider(INotificationProvider notificationProvider) public void SetNotificationProvider(INotificationProvider notificationProvider)
{ {
if (ReferenceEquals(_notificationProvider, notificationProvider))
return;
_notificationProvider?.Dispose();
_notificationProvider = notificationProvider; _notificationProvider = notificationProvider;
} }
@ -72,22 +76,32 @@ namespace Artemis.UI.Shared.Services
} }
/// <inheritdoc /> /// <inheritdoc />
public void ShowNotification(string title, string message) public void ShowNotification(string title, string message, Action? activatedCallback = null, Action? dismissedCallback = null)
{ {
_notificationProvider?.ShowNotification(title, message, PackIconKind.None); _notificationProvider?.ShowNotification(title, message, PackIconKind.None, activatedCallback, dismissedCallback);
} }
/// <inheritdoc /> /// <inheritdoc />
public void ShowNotification(string title, string message, PackIconKind icon) public void ShowNotification(string title, string message, PackIconKind icon, Action? activatedCallback = null, Action? dismissedCallback = null)
{ {
_notificationProvider?.ShowNotification(title, message, icon); _notificationProvider?.ShowNotification(title, message, icon, activatedCallback, dismissedCallback);
} }
/// <inheritdoc /> /// <inheritdoc />
public void ShowNotification(string title, string message, string icon) public void ShowNotification(string title, string message, string icon, Action? activatedCallback = null, Action? dismissedCallback = null)
{ {
Enum.TryParse(typeof(PackIconKind), icon, true, out object? iconKind); Enum.TryParse(typeof(PackIconKind), icon, true, out object? iconKind);
_notificationProvider?.ShowNotification(title, message, (PackIconKind) (iconKind ?? PackIconKind.None)); _notificationProvider?.ShowNotification(title, message, (PackIconKind) (iconKind ?? PackIconKind.None), activatedCallback, dismissedCallback);
} }
#region IDisposable
/// <inheritdoc />
public void Dispose()
{
_notificationProvider?.Dispose();
}
#endregion
} }
} }

View File

@ -118,10 +118,10 @@ namespace Artemis.UI
private void UtilitiesOnShutdownRequested(object sender, EventArgs e) private void UtilitiesOnShutdownRequested(object sender, EventArgs e)
{ {
// Use PowerShell to kill the process after 2 sec just in case // Use PowerShell to kill the process after 8 sec just in case
ProcessStartInfo info = new() ProcessStartInfo info = new()
{ {
Arguments = "-Command \"& {Start-Sleep -s 2; (Get-Process 'Artemis.UI').kill()}", Arguments = "-Command \"& {Start-Sleep -s 8; (Get-Process 'Artemis.UI').kill()}",
WindowStyle = ProcessWindowStyle.Hidden, WindowStyle = ProcessWindowStyle.Hidden,
CreateNoWindow = true, CreateNoWindow = true,
FileName = "PowerShell.exe" FileName = "PowerShell.exe"

View File

@ -1,372 +1,376 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework> <TargetFramework>net5.0-windows10.0.17763.0</TargetFramework>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<AssemblyTitle>Artemis</AssemblyTitle> <AssemblyTitle>Artemis</AssemblyTitle>
<Product>Artemis</Product> <Product>Artemis</Product>
<NeutralLanguage>en-US</NeutralLanguage> <NeutralLanguage>en-US</NeutralLanguage>
<Description>Provides advanced unified lighting across many different brands RGB peripherals</Description> <Description>Provides advanced unified lighting across many different brands RGB peripherals</Description>
<Copyright>Copyright © Robert Beekman - 2021</Copyright> <Copyright>Copyright © Robert Beekman - 2021</Copyright>
<FileVersion>2.0.0.0</FileVersion> <FileVersion>2.0.0.0</FileVersion>
<OutputPath>bin\</OutputPath> <OutputPath>bin\net5.0-windows\</OutputPath>
<UseWPF>true</UseWPF> <AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
<Platforms>x64</Platforms> <UseWPF>true</UseWPF>
<SupportedPlatform>windows</SupportedPlatform> <Platforms>x64</Platforms>
</PropertyGroup> <SupportedPlatform>windows</SupportedPlatform>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> </PropertyGroup>
<PlatformTarget>x64</PlatformTarget> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
</PropertyGroup> <PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ApplicationIcon>Resources\Images\Logo\bow.ico</ApplicationIcon> <ApplicationIcon>Resources\Images\Logo\bow.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<PostBuildEvent /> <PostBuildEvent />
<AssemblyVersion>2.0.0.0</AssemblyVersion> <AssemblyVersion>2.0.0.0</AssemblyVersion>
<Version>2.0.0</Version> <Version>2.0.0</Version>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<NrtRevisionFormat>2.0-{chash:6}</NrtRevisionFormat> <NrtRevisionFormat>2.0-{chash:6}</NrtRevisionFormat>
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes> <NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
<NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute> <NrtResolveInformationalAttribute>true</NrtResolveInformationalAttribute>
<NrtResolveCopyright>true</NrtResolveCopyright> <NrtResolveCopyright>true</NrtResolveCopyright>
<NrtTagMatch>v[0-9]*</NrtTagMatch> <NrtTagMatch>v[0-9]*</NrtTagMatch>
<NrtRemoveTagV>true</NrtRemoveTagV> <NrtRemoveTagV>true</NrtRemoveTagV>
<NrtRequiredVcs>git</NrtRequiredVcs> <NrtRequiredVcs>git</NrtRequiredVcs>
<NrtShowRevision>true</NrtShowRevision> <NrtShowRevision>true</NrtShowRevision>
</PropertyGroup> </PropertyGroup>
<Target Name="SkiaCleanUpAfterBuild" AfterTargets="AfterBuild"> <Target Name="SkiaCleanUpAfterBuild" AfterTargets="AfterBuild">
<Delete Files="$(OutputPath)\libSkiaSharp.dylib" /> <Delete Files="$(OutputPath)\libSkiaSharp.dylib" />
</Target> </Target>
<ItemGroup> <ItemGroup>
<FluentValidationExcludedCultures Include="ar-DZ;cs;cs-CZ;da;de;es;fa;fi;fr;fr-FR;it;ko;mk;nl;pl;pt;pt-BR;ru;ru-ru;sv;tr;zh-CN;uz-Latn-UZ"> <FluentValidationExcludedCultures Include="ar-DZ;cs;cs-CZ;da;de;es;fa;fi;fr;fr-FR;it;ko;mk;nl;pl;pt;pt-BR;ru;ru-ru;sv;tr;zh-CN;uz-Latn-UZ">
<InProject>false</InProject> <InProject>false</InProject>
</FluentValidationExcludedCultures> </FluentValidationExcludedCultures>
</ItemGroup> </ItemGroup>
<Target Name="RemoveTranslationsAfterBuild" AfterTargets="AfterBuild"> <Target Name="RemoveTranslationsAfterBuild" AfterTargets="AfterBuild">
<RemoveDir Directories="@(FluentValidationExcludedCultures->'$(OutputPath)%(Filename)')" /> <RemoveDir Directories="@(FluentValidationExcludedCultures->'$(OutputPath)%(Filename)')" />
</Target> </Target>
<ItemGroup> <ItemGroup>
<Compile Remove="publish\**" /> <Compile Remove="publish\**" />
<EmbeddedResource Remove="publish\**" /> <EmbeddedResource Remove="publish\**" />
<None Remove="publish\**" /> <None Remove="publish\**" />
<Page Remove="publish\**" /> <Page Remove="publish\**" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<!-- TODO: Remove when moving to Nuget, this is so the plugin templates have the DLL to reference --> <!-- TODO: Remove when moving to Nuget, this is so the plugin templates have the DLL to reference -->
<Reference Include="RGB.NET.Core"> <Reference Include="RGB.NET.Core">
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll</HintPath> <HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="RGB.NET.Layout"> <Reference Include="RGB.NET.Layout">
<HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll</HintPath> <HintPath>..\..\..\RGB.NET\bin\net5.0\RGB.NET.Layout.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Management" /> <Reference Include="System.Management" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx"> <EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj"> <ProjectReference Include="..\Artemis.Core\Artemis.Core.csproj">
<Private>true</Private> <Private>true</Private>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj"> <ProjectReference Include="..\Artemis.Storage\Artemis.Storage.csproj">
<Private>true</Private> <Private>true</Private>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj"> <ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj">
<Private>true</Private> <Private>true</Private>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Resources\Fonts\RobotoMono-Regular.ttf" /> <Resource Include="Resources\Fonts\RobotoMono-Regular.ttf" />
<Resource Include="Resources\Images\Logo\bow-white.ico" /> <Resource Include="Resources\Images\Logo\bow-black.ico" />
<Resource Include="Resources\Images\Logo\bow-white.svg" /> <Resource Include="Resources\Images\Logo\bow-white.ico" />
<Resource Include="Resources\Images\Logo\bow.ico" /> <Resource Include="Resources\Images\Logo\bow-white.svg" />
</ItemGroup> <Resource Include="Resources\Images\Logo\bow.ico" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate_tl.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_rotate_tl.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate_tr.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_rotate_tr.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate_bl.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_rotate_bl.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate_br.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_rotate_br.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_crosshair.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_crosshair.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_crosshair_minus.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_crosshair_minus.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_crosshair_plus.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_crosshair_plus.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_pen_min.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_pen_min.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_pen_plus.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_pen_plus.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_fill.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_fill.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_drag.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_drag.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_drag_ew.cur" /> <ItemGroup>
</ItemGroup> <Resource Include="Resources\Cursors\aero_drag_ew.cur" />
<ItemGroup> </ItemGroup>
<Resource Include="Resources\Cursors\aero_rotate.cur" /> <ItemGroup>
<Resource Include="Resources\Images\Logo\bow.svg" /> <Resource Include="Resources\Cursors\aero_rotate.cur" />
<Resource Include="Resources\Images\PhysicalLayouts\abnt.png" /> <Resource Include="Resources\Images\Logo\bow.svg" />
<Resource Include="Resources\Images\PhysicalLayouts\ansi.png" /> <Resource Include="Resources\Images\PhysicalLayouts\abnt.png" />
<Resource Include="Resources\Images\PhysicalLayouts\iso.png" /> <Resource Include="Resources\Images\PhysicalLayouts\ansi.png" />
<Resource Include="Resources\Images\PhysicalLayouts\jis.png" /> <Resource Include="Resources\Images\PhysicalLayouts\iso.png" />
<Resource Include="Resources\Images\PhysicalLayouts\ks.png" /> <Resource Include="Resources\Images\PhysicalLayouts\jis.png" />
<Resource Include="Resources\Images\Sidebar\sidebar-header.png" /> <Resource Include="Resources\Images\PhysicalLayouts\ks.png" />
</ItemGroup> <Resource Include="Resources\Images\Sidebar\sidebar-header.png" />
<ItemGroup> </ItemGroup>
<PackageReference Include="FluentValidation" Version="10.0.0" /> <ItemGroup>
<PackageReference Include="Flurl.Http" Version="3.0.1" /> <PackageReference Include="FluentValidation" Version="10.1.0" />
<PackageReference Include="gong-wpf-dragdrop" Version="2.3.2" /> <PackageReference Include="Flurl.Http" Version="3.0.1" />
<PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.18" /> <PackageReference Include="gong-wpf-dragdrop" Version="2.3.2" />
<PackageReference Include="Humanizer.Core" Version="2.8.26" /> <PackageReference Include="Hardcodet.NotifyIcon.Wpf.NetCore" Version="1.0.18" />
<PackageReference Include="MaterialDesignExtensions" Version="3.3.0" /> <PackageReference Include="Humanizer.Core" Version="2.8.26" />
<PackageReference Include="MaterialDesignThemes" Version="4.0.0" /> <PackageReference Include="MaterialDesignExtensions" Version="3.3.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" /> <PackageReference Include="MaterialDesignThemes" Version="4.0.0" />
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.31" /> <PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.0.2" />
<PackageReference Include="Ninject" Version="3.3.4" /> <PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" /> <PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.31" />
<PackageReference Include="Ookii.Dialogs.Wpf" Version="3.1.0" /> <PackageReference Include="Ninject" Version="3.3.4" />
<PackageReference Include="RawInput.Sharp" Version="0.0.3" /> <PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0" />
<PackageReference Include="Serilog" Version="2.10.0" /> <PackageReference Include="Ookii.Dialogs.Wpf" Version="3.1.0" />
<PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" /> <PackageReference Include="RawInput.Sharp" Version="0.0.3" />
<PackageReference Include="SkiaSharp.Vulkan.SharpVk" Version="2.80.2" /> <PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Stylet" Version="1.3.6" /> <PackageReference Include="SkiaSharp.Views.WPF" Version="2.80.2" />
<PackageReference Include="System.Buffers" Version="4.5.1" /> <PackageReference Include="SkiaSharp.Vulkan.SharpVk" Version="2.80.2" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="Stylet" Version="1.3.6" />
<PackageReference Include="System.Drawing.Common" Version="5.0.2" /> <PackageReference Include="System.Buffers" Version="4.5.1" />
<PackageReference Include="System.Management" Version="5.0.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" /> <PackageReference Include="System.Drawing.Common" Version="5.0.2" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" /> <PackageReference Include="System.Management" Version="5.0.0" />
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.0"> <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PrivateAssets>all</PrivateAssets> <PackageReference Include="System.ValueTuple" Version="4.5.0" />
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.0">
</PackageReference> <PrivateAssets>all</PrivateAssets>
</ItemGroup> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<ItemGroup> </PackageReference>
<Compile Remove="obj\x64\Debug\App.g.cs" /> </ItemGroup>
<Compile Remove="obj\x64\Debug\App.g.i.cs" /> <ItemGroup>
<Compile Remove="obj\x64\Debug\GeneratedInternalTypeHelper.g.cs" /> <Compile Remove="obj\x64\Debug\App.g.cs" />
<Compile Remove="obj\x64\Debug\GeneratedInternalTypeHelper.g.i.cs" /> <Compile Remove="obj\x64\Debug\App.g.i.cs" />
<Compile Remove="obj\x64\Release\App.g.cs" /> <Compile Remove="obj\x64\Debug\GeneratedInternalTypeHelper.g.cs" />
<Compile Remove="obj\x64\Release\GeneratedInternalTypeHelper.g.cs" /> <Compile Remove="obj\x64\Debug\GeneratedInternalTypeHelper.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\RootView.g.cs" /> <Compile Remove="obj\x64\Release\App.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\RootView.g.i.cs" /> <Compile Remove="obj\x64\Release\GeneratedInternalTypeHelper.g.cs" />
<Compile Remove="obj\x64\Release\Screens\RootView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\RootView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Dialogs\ConfirmDialogView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\RootView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Dialogs\ConfirmDialogView.g.i.cs" /> <Compile Remove="obj\x64\Release\Screens\RootView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\GradientEditor\GradientEditorView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Dialogs\ConfirmDialogView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\GradientEditor\GradientEditorView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Dialogs\ConfirmDialogView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Home\HomeView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\GradientEditor\GradientEditorView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Home\HomeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\GradientEditor\GradientEditorView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ModuleRootView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Home\HomeView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ModuleRootView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Home\HomeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\News\NewsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ModuleRootView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\News\NewsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ModuleRootView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\SettingsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\News\NewsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\SettingsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\News\NewsView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Sidebar\SidebarView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\SettingsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Sidebar\SidebarView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\SettingsView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Splash\SplashView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Sidebar\SidebarView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Splash\SplashView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Sidebar\SidebarView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\SurfaceEditorView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Splash\SplashView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\SurfaceEditorView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Splash\SplashView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Workshop\WorkshopView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\SurfaceEditorView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Workshop\WorkshopView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\SurfaceEditorView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\Dialogs\ConfirmDialogView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Workshop\WorkshopView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Home\HomeView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Workshop\WorkshopView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ModuleRootView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Dialogs\ConfirmDialogView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\News\NewsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Home\HomeView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Settings\SettingsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ModuleRootView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Splash\SplashView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\News\NewsView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Workshop\WorkshopView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Settings\SettingsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileEditorView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Splash\SplashView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileEditorView.g.i.cs" /> <Compile Remove="obj\x64\Release\Screens\Workshop\WorkshopView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\Debug\DebugView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileEditorView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\Debug\DebugView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileEditorView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\Debug\DebugView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\Debug\DebugView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ProfileEditorView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Settings\Debug\DebugView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ProfileEditorView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Settings\Debug\DebugView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Dialogs\SurfaceCreateView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Dialogs\SurfaceDeviceConfigView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Visualization\SurfaceDeviceView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.i.cs" /> <Compile Remove="obj\x64\Release\Screens\SurfaceEditor\Visualization\SurfaceLedView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Layers\LayersView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\LayerPropertiesView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Layers\LayersView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\ProfileTreeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLayerView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLayerView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLayerView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLayerView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\ProfileView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.i.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Layers\LayersView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Layers\LayersView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileDeviceView.g.cs" />
<Compile Remove="obj\x64\Release\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileLedView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\Dialogs\AddLayerElementView.g.i.cs" /> <Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Visualization\ProfileView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.g.cs" /> <Compile Remove="obj\x64\Release\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\Dialogs\AddLayerElementView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeItemView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeChildView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeItemView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\LayerPropertiesTimelineView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyRailItemView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyTreeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\LayerPropertiesTimelineView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyRailItemView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTimelineView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineKeyframeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePartView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\PropertyTrackView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyRailView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineKeyframeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePartView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineTimeView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyRailView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelinePropertyView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\Timeline\TimelineTimeView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\FolderView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EditToolView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EditToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ProfileTree\TreeItem\LayerView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EllipseToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EditToolView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\FillToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EditToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\PolygonToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\EllipseToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\RectangleToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\FillToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionAddToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\PolygonToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionRemoveToolView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\RectangleToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionRemoveToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionAddToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionToolView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionRemoveToolView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionRemoveToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\ViewpointMoveToolView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionToolView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\ViewpointMoveToolView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\SelectionToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\UserControls\LayerShapeControl.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\ViewpointMoveToolView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\UserControls\LayerShapeControl.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\Tools\ViewpointMoveToolView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\BrushPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\UserControls\LayerShapeControl.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\BrushPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Visualization\UserControls\LayerShapeControl.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\EnumPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\BrushPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\EnumPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\BrushPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\FloatPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\EnumPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\FloatPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\EnumPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView - Copy.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\FloatPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\FloatPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView - Copy.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKColorPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKColorPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\IntPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKPointPropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKColorPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKPointPropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKColorPropertyInputView.g.i.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKSizePropertyInputView.g.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKPointPropertyInputView.g.cs" />
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKSizePropertyInputView.g.i.cs" /> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKPointPropertyInputView.g.i.cs" />
</ItemGroup> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKSizePropertyInputView.g.cs" />
<ItemGroup> <Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerProperties\PropertyTree\PropertyInput\SKSizePropertyInputView.g.i.cs" />
<None Remove="Resources\Fonts\RobotoMono-Regular.ttf" /> </ItemGroup>
<None Remove="Resources\Images\Logo\bow-white.ico" /> <ItemGroup>
<None Remove="Resources\Images\Logo\bow-white.svg" /> <None Remove="Resources\Fonts\RobotoMono-Regular.ttf" />
<None Remove="Resources\Images\Logo\bow.ico" /> <None Remove="Resources\Images\Logo\bow-black.ico" />
<None Remove="Resources\Images\Logo\bow.svg" /> <None Remove="Resources\Images\Logo\bow-white.ico" />
<None Remove="Resources\Images\PhysicalLayouts\abnt.png" /> <None Remove="Resources\Images\Logo\bow-white.svg" />
<None Remove="Resources\Images\PhysicalLayouts\ansi.png" /> <None Remove="Resources\Images\Logo\bow.ico" />
<None Remove="Resources\Images\PhysicalLayouts\iso.png" /> <None Remove="Resources\Images\Logo\bow.svg" />
<None Remove="Resources\Images\PhysicalLayouts\jis.png" /> <None Remove="Resources\Images\PhysicalLayouts\abnt.png" />
<None Remove="Resources\Images\PhysicalLayouts\ks.png" /> <None Remove="Resources\Images\PhysicalLayouts\ansi.png" />
<None Remove="Resources\Images\Sidebar\sidebar-header.png" /> <None Remove="Resources\Images\PhysicalLayouts\iso.png" />
</ItemGroup> <None Remove="Resources\Images\PhysicalLayouts\jis.png" />
<ItemGroup> <None Remove="Resources\Images\PhysicalLayouts\ks.png" />
<None Include="..\.editorconfig" Link=".editorconfig" /> <None Remove="Resources\Images\Sidebar\sidebar-header.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Properties\Resources.Designer.cs"> <None Include="..\.editorconfig" Link=".editorconfig" />
<DesignTime>True</DesignTime> </ItemGroup>
<AutoGen>True</AutoGen> <ItemGroup>
<DependentUpon>Resources.resx</DependentUpon> <Compile Update="Properties\Resources.Designer.cs">
</Compile> <DesignTime>True</DesignTime>
<Compile Update="Properties\Settings.Designer.cs"> <AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DependentUpon>Resources.resx</DependentUpon>
<AutoGen>True</AutoGen> </Compile>
<DependentUpon>Settings.settings</DependentUpon> <Compile Update="Properties\Settings.Designer.cs">
</Compile> <DesignTimeSharedInput>True</DesignTimeSharedInput>
</ItemGroup> <AutoGen>True</AutoGen>
<ItemGroup> <DependentUpon>Settings.settings</DependentUpon>
<None Update="Properties\Settings.settings"> </Compile>
<Generator>SettingsSingleFileGenerator</Generator> </ItemGroup>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <ItemGroup>
</None> <None Update="Properties\Settings.settings">
</ItemGroup> <Generator>SettingsSingleFileGenerator</Generator>
<ItemGroup> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
<Page Update="DefaultTypes\DataModel\Display\SKColorDataModelDisplayView.xaml"> </None>
<SubType>Designer</SubType> </ItemGroup>
</Page> <ItemGroup>
<Page Update="DefaultTypes\DataModel\Input\DoubleDataModelInputView.xaml"> <Page Update="DefaultTypes\DataModel\Display\SKColorDataModelDisplayView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\DataModel\Input\IntDataModelInputView.xaml"> <Page Update="DefaultTypes\DataModel\Input\DoubleDataModelInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\DataModel\Input\SKColorDataModelInputView.xaml"> <Page Update="DefaultTypes\DataModel\Input\IntDataModelInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\DataModel\Input\StringDataModelInputView.xaml"> <Page Update="DefaultTypes\DataModel\Input\SKColorDataModelInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="DefaultTypes\PropertyInput\FloatRangePropertyInputView.xaml"> <Page Update="DefaultTypes\DataModel\Input\StringDataModelInputView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="Screens\Plugins\PluginPrerequisitesUninstallDialogView.xaml"> <Page Update="DefaultTypes\PropertyInput\FloatRangePropertyInputView.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime> <SubType>Designer</SubType>
</Page> </Page>
<Page Update="Screens\ProfileEditor\Dialogs\ProfileEditView.xaml"> <Page Update="Screens\Plugins\PluginPrerequisitesUninstallDialogView.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime> <XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page> </Page>
</ItemGroup> <Page Update="Screens\ProfileEditor\Dialogs\ProfileEditView.xaml">
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
</Page>
</ItemGroup>
</Project> </Project>

View File

@ -98,7 +98,7 @@ namespace Artemis.UI
}); });
IRegistrationService registrationService = Kernel.Get<IRegistrationService>(); IRegistrationService registrationService = Kernel.Get<IRegistrationService>();
registrationService.RegisterInputProvider(); registrationService.RegisterProviders();
registrationService.RegisterControllers(); registrationService.RegisterControllers();
Execute.OnUIThreadSync(() => { registrationService.ApplyPreferredGraphicsContext(); }); Execute.OnUIThreadSync(() => { registrationService.ApplyPreferredGraphicsContext(); });

View File

@ -1,11 +1,9 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Timers; using System.Timers;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Interop;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Utilities; using Artemis.UI.Utilities;
@ -14,7 +12,7 @@ using Linearstar.Windows.RawInput.Native;
using Serilog; using Serilog;
using MouseButton = Artemis.Core.Services.MouseButton; using MouseButton = Artemis.Core.Services.MouseButton;
namespace Artemis.UI.InputProviders namespace Artemis.UI.Providers
{ {
public class NativeWindowInputProvider : InputProvider public class NativeWindowInputProvider : InputProvider
{ {

View File

@ -1,7 +1,7 @@
using System; using System;
using System.Windows.Forms; using System.Windows.Forms;
namespace Artemis.UI.InputProviders namespace Artemis.UI.Providers
{ {
public sealed class SpongeWindow : NativeWindow public sealed class SpongeWindow : NativeWindow
{ {

View File

@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Windows.UI.Notifications;
using Artemis.UI.Shared.Services;
using Artemis.UI.Utilities;
using MaterialDesignThemes.Wpf;
using Microsoft.Toolkit.Uwp.Notifications;
using Stylet;
namespace Artemis.UI.Providers
{
public class ToastNotificationProvider : INotificationProvider
{
private ThemeWatcher _themeWatcher;
public ToastNotificationProvider()
{
_themeWatcher = new ThemeWatcher();
}
public static PngBitmapEncoder GetEncoderForIcon(PackIconKind icon, Color color)
{
// Convert the PackIcon to an icon by drawing it on a visual
DrawingVisual drawingVisual = new();
DrawingContext drawingContext = drawingVisual.RenderOpen();
PackIcon packIcon = new() {Kind = icon};
Geometry geometry = Geometry.Parse(packIcon.Data);
// Scale the icon up to fit a 256x256 image and draw it
geometry = Geometry.Combine(geometry, Geometry.Empty, GeometryCombineMode.Union, new ScaleTransform(256 / geometry.Bounds.Right, 256 / geometry.Bounds.Bottom));
drawingContext.DrawGeometry(new SolidColorBrush(color), null, geometry);
drawingContext.Close();
// Render the visual and add it to a PNG encoder (we want opacity in our icon)
RenderTargetBitmap renderTargetBitmap = new(256, 256, 96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(drawingVisual);
PngBitmapEncoder encoder = new();
encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
return encoder;
}
private void ToastDismissed(string imagePath, Action dismissedCallback)
{
if (File.Exists(imagePath))
File.Delete(imagePath);
dismissedCallback?.Invoke();
}
private void ToastActivated(string imagePath, Action activatedCallback)
{
if (File.Exists(imagePath))
File.Delete(imagePath);
activatedCallback?.Invoke();
}
#region Implementation of INotificationProvider
/// <inheritdoc />
public void ShowNotification(string title, string message, PackIconKind icon, Action activatedCallback, Action dismissedCallback)
{
string imagePath = Path.GetTempFileName().Replace(".tmp", "png");
Execute.OnUIThreadSync(() =>
{
using FileStream stream = File.OpenWrite(imagePath);
GetEncoderForIcon(icon, _themeWatcher.GetWindowsTheme() == ThemeWatcher.WindowsTheme.Dark ? Colors.White : Colors.Black).Save(stream);
});
new ToastContentBuilder()
.AddAppLogoOverride(new Uri(imagePath))
.AddText(title, AdaptiveTextStyle.Header)
.AddText(message)
.Show(t =>
{
t.Dismissed += (_, _) => ToastDismissed(imagePath, dismissedCallback);
t.Activated += (_, _) => ToastActivated(imagePath, activatedCallback);
t.Data = new NotificationData(new List<KeyValuePair<string, string>> {new("image", imagePath)});
});
}
#endregion
#region IDisposable
/// <inheritdoc />
public void Dispose()
{
ToastNotificationManagerCompat.Uninstall();
}
#endregion
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@ -11,7 +11,7 @@
mc:Ignorable="d" mc:Ignorable="d"
d:DesignHeight="574.026" d:DesignHeight="574.026"
d:DesignWidth="1029.87" d:DesignWidth="1029.87"
d:DataContext="{d:DesignInstance home:HomeViewModel, IsDesignTimeCreatable=True}"> d:DataContext="{d:DesignInstance home:HomeViewModel}">
<UserControl.Resources> <UserControl.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
@ -38,22 +38,23 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Image Source="{svgc:SvgImage Source=/Resources/Images/Logo/bow.svg}" Height="100" Width="100"/> <Image Source="{svgc:SvgImage Source=/Resources/Images/Logo/bow.svg}" Height="100" Width="100" />
<StackPanel Grid.Column="1" Margin="24 0 0 0" VerticalAlignment="Center"> <StackPanel Grid.Column="1" Margin="24 0 0 0" VerticalAlignment="Center">
<TextBlock Style="{StaticResource MaterialDesignHeadline4TextBlock}" TextWrapping="Wrap"> <TextBlock Style="{StaticResource MaterialDesignHeadline4TextBlock}" TextWrapping="Wrap">
<Run Text="Welcome to Artemis, the unified"></Run> <Run Text="Welcome to Artemis, the unified" />
<Run Text="RGB"> <Run Text="RGB">
<Run.Foreground> <Run.Foreground>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1"> <LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="#f19d25"/> <GradientStop Color="#f19d25" />
<GradientStop Color="#f63d3d" Offset="0.2"/> <GradientStop Color="#f63d3d" Offset="0.2" />
<GradientStop Color="#c93cec" Offset="0.4"/> <GradientStop Color="#c93cec" Offset="0.4" />
<GradientStop Color="#2667f4" Offset="0.6"/> <GradientStop Color="#2667f4" Offset="0.6" />
<GradientStop Color="#1cb6e7" Offset="0.8"/> <GradientStop Color="#1cb6e7" Offset="0.8" />
<GradientStop Color="#2df4b5" Offset="1"/> <GradientStop Color="#2df4b5" Offset="1" />
</LinearGradientBrush> </LinearGradientBrush>
</Run.Foreground></Run> </Run.Foreground>
<Run Text="platform."></Run> </Run>
<Run Text="platform." />
</TextBlock> </TextBlock>
<Button Style="{StaticResource MaterialDesignFlatButton}" <Button Style="{StaticResource MaterialDesignFlatButton}"
Foreground="{StaticResource SecondaryHueMidBrush}" Foreground="{StaticResource SecondaryHueMidBrush}"
@ -70,124 +71,124 @@
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Bottom" VerticalAlignment="Bottom"
Margin="0 0 0 32"> Margin="0 0 0 32">
<Grid>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto"> <materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
<Grid VerticalAlignment="Stretch"> <Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="155" /> <RowDefinition Height="155" />
<RowDefinition Height="95" /> <RowDefinition Height="95" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="200" /> <ColumnDefinition Width="200" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<materialDesign:PackIcon Kind="Discord" Width="140" Height="140" <materialDesign:PackIcon Kind="Discord" Width="140" Height="140"
HorizontalAlignment="Center" VerticalAlignment="Center" /> HorizontalAlignment="Center" VerticalAlignment="Center" />
<StackPanel Grid.Row="0" Grid.Column="1"> <StackPanel Grid.Row="0" Grid.Column="1">
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Have a chat</TextBlock> <TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Have a chat</TextBlock>
<TextBlock TextWrapping="Wrap" Margin="16 0 16 8" <TextBlock TextWrapping="Wrap" Margin="16 0 16 8"
Foreground="{DynamicResource MaterialDesignBodyLight}" Foreground="{DynamicResource MaterialDesignBodyLight}"
VerticalAlignment="Top"> VerticalAlignment="Top">
If you need help, have some feedback or have any other questions feel free to contact us through any of the If you need help, have some feedback or have any other questions feel free to contact us through any of the
following channels. following channels.
</TextBlock> </TextBlock>
</StackPanel> </StackPanel>
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0" <Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0"
BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8"> BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
<DockPanel> <DockPanel>
<Grid Margin="8"> <Grid Margin="8">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Button Style="{DynamicResource MaterialDesignFlatButton}"
HorizontalAlignment="Left"
x:Name="GitHubButton" Command="{s:Action OpenUrl}"
CommandParameter="https://github.com/Artemis-RGB/Artemis">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Github" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">GitHub</TextBlock>
</StackPanel>
</Button>
<Button Grid.Row="0" Style="{DynamicResource MaterialDesignFlatButton}"
HorizontalAlignment="Right"
x:Name="WebsiteButton" Command="{s:Action OpenUrl}"
CommandParameter="https://artemis-rgb.com">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Web" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Website</TextBlock>
</StackPanel>
</Button>
<Button Grid.Row="1" Style="{DynamicResource MaterialDesignFlatButton}"
HorizontalAlignment="Left"
x:Name="DiscordButton" Command="{s:Action OpenUrl}"
CommandParameter="https://discordapp.com/invite/S3MVaC9">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Discord" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Discord</TextBlock>
</StackPanel>
</Button>
<Button Grid.Row="1" Style="{DynamicResource MaterialDesignFlatButton}"
HorizontalAlignment="Right"
x:Name="MailButton" Command="{s:Action OpenUrl}"
CommandParameter="mailto:spoinky.nl@gmail.com">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Email" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">E-mail</TextBlock>
</StackPanel>
</Button>
</Grid>
</DockPanel>
</Border>
</Grid>
</materialDesign:Card>
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="155" />
<RowDefinition Height="95" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<materialDesign:PackIcon Kind="Github" Width="160" Height="160"
HorizontalAlignment="Center" VerticalAlignment="Center" />
<StackPanel Grid.Row="0" Grid.Column="1">
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Open Source</TextBlock>
<TextBlock TextWrapping="Wrap" Margin="16 0 16 8"
Foreground="{DynamicResource MaterialDesignBodyLight}"
VerticalAlignment="Top">
This project is completely open source. If you like it and want to say thanks you could hit the GitHub Star button,
I like numbers. You could even make plugins, there's a full documentation on the website
</TextBlock>
</StackPanel>
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0"
BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
<DockPanel>
<Button Style="{DynamicResource MaterialDesignFlatButton}" <Button Style="{DynamicResource MaterialDesignFlatButton}"
DockPanel.Dock="Right" HorizontalAlignment="Left"
x:Name="DonateButton" x:Name="GitHubButton" Command="{s:Action OpenUrl}"
Command="{s:Action OpenUrl}" CommandParameter="https://github.com/Artemis-RGB/Artemis">
CommandParameter="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=VQBAEJYUFLU4J">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Gift" /> <materialDesign:PackIcon Kind="Github" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Donate</TextBlock> <TextBlock Margin="8 0 0 0" VerticalAlignment="Center">GitHub</TextBlock>
</StackPanel> </StackPanel>
</Button> </Button>
<TextBlock Foreground="{DynamicResource MaterialDesignBodyLight}" <Button Grid.Row="0" Style="{DynamicResource MaterialDesignFlatButton}"
TextWrapping="Wrap" HorizontalAlignment="Right"
Margin="16" x:Name="WebsiteButton" Command="{s:Action OpenUrl}"
VerticalAlignment="Center"> CommandParameter="https://artemis-rgb.com">
Feel like you want to make a donation? It would be gratefully received. Click the button to donate via PayPal. <StackPanel Orientation="Horizontal">
</TextBlock> <materialDesign:PackIcon Kind="Web" />
</DockPanel> <TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Website</TextBlock>
</Border> </StackPanel>
</Grid> </Button>
</materialDesign:Card> <Button Grid.Row="1" Style="{DynamicResource MaterialDesignFlatButton}"
</StackPanel> HorizontalAlignment="Left"
</Grid> x:Name="DiscordButton" Command="{s:Action OpenUrl}"
CommandParameter="https://discordapp.com/invite/S3MVaC9">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Discord" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Discord</TextBlock>
</StackPanel>
</Button>
<Button Grid.Row="1" Style="{DynamicResource MaterialDesignFlatButton}"
HorizontalAlignment="Right"
x:Name="MailButton" Command="{s:Action OpenUrl}"
CommandParameter="mailto:spoinky.nl@gmail.com">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Email" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">E-mail</TextBlock>
</StackPanel>
</Button>
</Grid>
</DockPanel>
</Border>
</Grid>
</materialDesign:Card>
<materialDesign:Card Width="420" Margin="8 2 4 16" Height="Auto">
<Grid VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="155" />
<RowDefinition Height="95" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<materialDesign:PackIcon Kind="Github" Width="160" Height="160"
HorizontalAlignment="Center" VerticalAlignment="Center" />
<StackPanel Grid.Row="0" Grid.Column="1">
<TextBlock Style="{StaticResource MaterialDesignHeadline5TextBlock}" Margin="16 16 16 8">Open Source</TextBlock>
<TextBlock TextWrapping="Wrap" Margin="16 0 16 8"
Foreground="{DynamicResource MaterialDesignBodyLight}"
VerticalAlignment="Top">
This project is completely open source. If you like it and want to say thanks you could hit the GitHub Star button,
I like numbers. You could even make plugins, there's a full documentation on the website
</TextBlock>
</StackPanel>
<Border Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" BorderThickness="0 1 0 0"
BorderBrush="{DynamicResource MaterialDesignDivider}" Padding="8">
<DockPanel>
<Button Style="{DynamicResource MaterialDesignFlatButton}"
DockPanel.Dock="Right"
x:Name="DonateButton"
Command="{s:Action OpenUrl}"
CommandParameter="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=VQBAEJYUFLU4J">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Gift" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Donate</TextBlock>
</StackPanel>
</Button>
<TextBlock Foreground="{DynamicResource MaterialDesignBodyLight}"
TextWrapping="Wrap"
Margin="16"
VerticalAlignment="Center">
Feel like you want to make a donation? It would be gratefully received. Click the button to donate via PayPal.
</TextBlock>
</DockPanel>
</Border>
</Grid>
</materialDesign:Card>
</StackPanel>
</ScrollViewer> </ScrollViewer>
<!-- PopupBox could be nice in the future when we actually have some stuff to send ppl to --> <!-- PopupBox could be nice in the future when we actually have some stuff to send ppl to -->
<!--<materialDesign:PopupBox Style="{StaticResource MaterialDesignMultiFloatingActionPopupBox}" <!--<materialDesign:PopupBox Style="{StaticResource MaterialDesignMultiFloatingActionPopupBox}"

View File

@ -35,13 +35,13 @@
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" /> <TextBlock Text="{Binding Name}" VerticalAlignment="Center" />
<Button Grid.Column="1" <Button Grid.Column="1"
Style="{StaticResource MaterialDesignFloatingActionMiniDarkButton}" Style="{StaticResource MaterialDesignIconForegroundButton}"
Width="26" Width="26"
Height="26" Height="26"
VerticalAlignment="Top" VerticalAlignment="Top"
Command="{s:Action DeleteProfile}" Command="{s:Action DeleteProfile}"
CommandParameter="{Binding}"> CommandParameter="{Binding}">
<materialDesign:PackIcon Kind="TrashCanOutline" Height="14" Width="14" HorizontalAlignment="Right" /> <materialDesign:PackIcon Kind="Delete" Height="16" Width="16" HorizontalAlignment="Right" />
</Button> </Button>
</Grid> </Grid>
</DataTemplate> </DataTemplate>

View File

@ -14,7 +14,6 @@ using Artemis.UI.Screens.ProfileEditor.LayerProperties;
using Artemis.UI.Screens.ProfileEditor.ProfileTree; using Artemis.UI.Screens.ProfileEditor.ProfileTree;
using Artemis.UI.Screens.ProfileEditor.Visualization; using Artemis.UI.Screens.ProfileEditor.Visualization;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using MaterialDesignThemes.Wpf;
using Stylet; using Stylet;
namespace Artemis.UI.Screens.ProfileEditor namespace Artemis.UI.Screens.ProfileEditor
@ -388,7 +387,7 @@ namespace Artemis.UI.Screens.ProfileEditor
{ {
// Get all profiles from the database // Get all profiles from the database
Profiles.Clear(); Profiles.Clear();
Profiles.AddRange(_profileService.GetProfileDescriptors(Module).OrderBy(d => d.Name)); Profiles.AddRange(_profileService.GetProfileDescriptors(Module).OrderBy(p => p.Name));
} }
} }
} }

View File

@ -7,7 +7,7 @@
xmlns:s="https://github.com/canton7/Stylet" xmlns:s="https://github.com/canton7/Stylet"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"> mc:Ignorable="d">
<tb:TaskbarIcon IconSource="/Resources/Images/Logo/bow-white.ico" <tb:TaskbarIcon IconSource="{Binding Icon}"
MenuActivation="LeftOrRightClick" MenuActivation="LeftOrRightClick"
PopupActivation="DoubleClick" PopupActivation="DoubleClick"
DoubleClickCommand="{s:Action TrayBringToForeground}" DoubleClickCommand="{s:Action TrayBringToForeground}"

View File

@ -1,6 +1,4 @@
using System; using System;
using System.Drawing;
using System.IO;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
@ -17,26 +15,25 @@ using Hardcodet.Wpf.TaskbarNotification;
using MaterialDesignThemes.Wpf; using MaterialDesignThemes.Wpf;
using Ninject; using Ninject;
using Stylet; using Stylet;
using Icon = System.Drawing.Icon;
namespace Artemis.UI.Screens namespace Artemis.UI.Screens
{ {
public class TrayViewModel : Screen, IMainWindowProvider, INotificationProvider public class TrayViewModel : Screen, IMainWindowProvider
{ {
private readonly PluginSetting<ApplicationColorScheme> _colorScheme;
private readonly IDebugService _debugService; private readonly IDebugService _debugService;
private readonly IEventAggregator _eventAggregator; private readonly IEventAggregator _eventAggregator;
private readonly IKernel _kernel; private readonly IKernel _kernel;
private readonly IWindowManager _windowManager;
private readonly ThemeWatcher _themeWatcher; private readonly ThemeWatcher _themeWatcher;
private readonly PluginSetting<ApplicationColorScheme> _colorScheme; private readonly IWindowManager _windowManager;
private RootViewModel _rootViewModel; private RootViewModel _rootViewModel;
private SplashViewModel _splashViewModel; private SplashViewModel _splashViewModel;
private TaskbarIcon _taskBarIcon; private TaskbarIcon _taskBarIcon;
private ImageSource _icon;
public TrayViewModel(IKernel kernel, public TrayViewModel(IKernel kernel,
IWindowManager windowManager, IWindowManager windowManager,
IWindowService windowService, IWindowService windowService,
IMessageService messageService,
IUpdateService updateService, IUpdateService updateService,
IEventAggregator eventAggregator, IEventAggregator eventAggregator,
ICoreService coreService, ICoreService coreService,
@ -59,7 +56,6 @@ namespace Artemis.UI.Screens
ApplyColorSchemeSetting(); ApplyColorSchemeSetting();
windowService.ConfigureMainWindowProvider(this); windowService.ConfigureMainWindowProvider(this);
messageService.ConfigureNotificationProvider(this);
bool autoRunning = Bootstrapper.StartupArguments.Contains("--autorun"); bool autoRunning = Bootstrapper.StartupArguments.Contains("--autorun");
bool minimized = Bootstrapper.StartupArguments.Contains("--minimized"); bool minimized = Bootstrapper.StartupArguments.Contains("--minimized");
bool showOnAutoRun = settingsService.GetSetting("UI.ShowOnStartup", true).Value; bool showOnAutoRun = settingsService.GetSetting("UI.ShowOnStartup", true).Value;
@ -97,6 +93,12 @@ namespace Artemis.UI.Screens
OnMainWindowOpened(); OnMainWindowOpened();
} }
public ImageSource Icon
{
get => _icon;
set => SetAndNotify(ref _icon, value);
}
public void TrayActivateSidebarItem(string sidebarItem) public void TrayActivateSidebarItem(string sidebarItem)
{ {
TrayBringToForeground(); TrayBringToForeground();
@ -175,9 +177,15 @@ namespace Artemis.UI.Screens
private void ApplyWindowsTheme(ThemeWatcher.WindowsTheme windowsTheme) private void ApplyWindowsTheme(ThemeWatcher.WindowsTheme windowsTheme)
{ {
Execute.PostToUIThread(() =>
{
Icon = windowsTheme == ThemeWatcher.WindowsTheme.Dark
? new BitmapImage(new Uri("pack://application:,,,/Artemis.UI;component/Resources/Images/Logo/bow-white.ico"))
: new BitmapImage(new Uri("pack://application:,,,/Artemis.UI;component/Resources/Images/Logo/bow-black.ico"));
});
if (_colorScheme.Value != ApplicationColorScheme.Automatic) if (_colorScheme.Value != ApplicationColorScheme.Automatic)
return; return;
if (windowsTheme == ThemeWatcher.WindowsTheme.Dark) if (windowsTheme == ThemeWatcher.WindowsTheme.Dark)
ChangeMaterialColors(ApplicationColorScheme.Dark); ChangeMaterialColors(ApplicationColorScheme.Dark);
else else
@ -207,43 +215,6 @@ namespace Artemis.UI.Screens
#endregion #endregion
#region Implementation of INotificationProvider
/// <inheritdoc />
public void ShowNotification(string title, string message, PackIconKind icon)
{
Execute.OnUIThread(() =>
{
// Convert the PackIcon to an icon by drawing it on a visual
DrawingVisual drawingVisual = new();
DrawingContext drawingContext = drawingVisual.RenderOpen();
PackIcon packIcon = new() {Kind = icon};
Geometry geometry = Geometry.Parse(packIcon.Data);
// Scale the icon up to fit a 256x256 image and draw it
geometry = Geometry.Combine(geometry, Geometry.Empty, GeometryCombineMode.Union, new ScaleTransform(256 / geometry.Bounds.Right, 256 / geometry.Bounds.Bottom));
drawingContext.DrawGeometry(new SolidColorBrush(Colors.White), null, geometry);
drawingContext.Close();
// Render the visual and add it to a PNG encoder (we want opacity in our icon)
RenderTargetBitmap renderTargetBitmap = new(256, 256, 96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(drawingVisual);
PngBitmapEncoder encoder = new();
encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
// Save the PNG and get an icon handle
using MemoryStream stream = new();
encoder.Save(stream);
Icon convertedIcon = Icon.FromHandle(new Bitmap(stream).GetHicon());
// Show the 'balloon'
_taskBarIcon.ShowBalloonTip(title, message, convertedIcon, true);
});
}
#endregion
#region Implementation of IMainWindowProvider #region Implementation of IMainWindowProvider
public bool IsMainWindowOpen { get; private set; } public bool IsMainWindowOpen { get; private set; }

View File

@ -6,8 +6,8 @@ using Artemis.UI.Controllers;
using Artemis.UI.DefaultTypes.DataModel.Display; using Artemis.UI.DefaultTypes.DataModel.Display;
using Artemis.UI.DefaultTypes.DataModel.Input; using Artemis.UI.DefaultTypes.DataModel.Input;
using Artemis.UI.DefaultTypes.PropertyInput; using Artemis.UI.DefaultTypes.PropertyInput;
using Artemis.UI.InputProviders;
using Artemis.UI.Ninject; using Artemis.UI.Ninject;
using Artemis.UI.Providers;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using Artemis.UI.SkiaSharp; using Artemis.UI.SkiaSharp;
using Serilog; using Serilog;
@ -22,6 +22,7 @@ namespace Artemis.UI.Services
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly IPluginManagementService _pluginManagementService; private readonly IPluginManagementService _pluginManagementService;
private readonly IInputService _inputService; private readonly IInputService _inputService;
private readonly IMessageService _messageService;
private readonly IWebServerService _webServerService; private readonly IWebServerService _webServerService;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
@ -36,6 +37,7 @@ namespace Artemis.UI.Services
IProfileEditorService profileEditorService, IProfileEditorService profileEditorService,
IPluginManagementService pluginManagementService, IPluginManagementService pluginManagementService,
IInputService inputService, IInputService inputService,
IMessageService messageService,
IWebServerService webServerService, IWebServerService webServerService,
IRgbService rgbService, IRgbService rgbService,
ISettingsService settingsService) ISettingsService settingsService)
@ -46,6 +48,7 @@ namespace Artemis.UI.Services
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_pluginManagementService = pluginManagementService; _pluginManagementService = pluginManagementService;
_inputService = inputService; _inputService = inputService;
_messageService = messageService;
_webServerService = webServerService; _webServerService = webServerService;
_rgbService = rgbService; _rgbService = rgbService;
_settingsService = settingsService; _settingsService = settingsService;
@ -99,9 +102,10 @@ namespace Artemis.UI.Services
_registeredBuiltInPropertyEditors = true; _registeredBuiltInPropertyEditors = true;
} }
public void RegisterInputProvider() public void RegisterProviders()
{ {
_inputService.AddInputProvider(new NativeWindowInputProvider(_logger, _inputService)); _inputService.AddInputProvider(new NativeWindowInputProvider(_logger, _inputService));
_messageService.SetNotificationProvider(new ToastNotificationProvider());
} }
public void RegisterControllers() public void RegisterControllers()
@ -160,7 +164,7 @@ namespace Artemis.UI.Services
void RegisterBuiltInDataModelDisplays(); void RegisterBuiltInDataModelDisplays();
void RegisterBuiltInDataModelInputs(); void RegisterBuiltInDataModelInputs();
void RegisterBuiltInPropertyEditors(); void RegisterBuiltInPropertyEditors();
void RegisterInputProvider(); void RegisterProviders();
void RegisterControllers(); void RegisterControllers();
void ApplyPreferredGraphicsContext(); void ApplyPreferredGraphicsContext();
} }

View File

@ -8,6 +8,7 @@ using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Timers; using System.Timers;
using Windows.UI.Notifications;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Exceptions; using Artemis.UI.Exceptions;
@ -16,9 +17,8 @@ using Artemis.UI.Services.Models.UpdateService;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using Flurl; using Flurl;
using Flurl.Http; using Flurl.Http;
using MaterialDesignThemes.Wpf; using Microsoft.Toolkit.Uwp.Notifications;
using Serilog; using Serilog;
using Constants = Artemis.Core.Constants;
using File = System.IO.File; using File = System.IO.File;
namespace Artemis.UI.Services namespace Artemis.UI.Services
@ -32,14 +32,12 @@ namespace Artemis.UI.Services
private readonly PluginSetting<bool> _checkForUpdates; private readonly PluginSetting<bool> _checkForUpdates;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IMessageService _messageService;
private readonly IWindowService _windowService; private readonly IWindowService _windowService;
public UpdateService(ILogger logger, ISettingsService settingsService, IDialogService dialogService, IMessageService messageService, IWindowService windowService) public UpdateService(ILogger logger, ISettingsService settingsService, IDialogService dialogService, IWindowService windowService)
{ {
_logger = logger; _logger = logger;
_dialogService = dialogService; _dialogService = dialogService;
_messageService = messageService;
_windowService = windowService; _windowService = windowService;
_windowService.MainWindowOpened += WindowServiceOnMainWindowOpened; _windowService.MainWindowOpened += WindowServiceOnMainWindowOpened;
@ -52,8 +50,6 @@ namespace Artemis.UI.Services
timer.Start(); timer.Start();
} }
public bool SuspendAutoUpdate { get; set; }
private async Task OfferUpdate(DevOpsBuild buildInfo) private async Task OfferUpdate(DevOpsBuild buildInfo)
{ {
object result = await _dialogService.ShowDialog<UpdateDialogViewModel>(new Dictionary<string, object> {{"buildInfo", buildInfo}}); object result = await _dialogService.ShowDialog<UpdateDialogViewModel>(new Dictionary<string, object> {{"buildInfo", buildInfo}});
@ -82,6 +78,31 @@ namespace Artemis.UI.Services
await httpResponseMessage.Content.CopyToAsync(fs); await httpResponseMessage.Content.CopyToAsync(fs);
} }
private async void TOnActivated(ToastNotification sender, object args)
{
if (args is not ToastActivatedEventArgs toastEventArgs)
return;
if (toastEventArgs.Arguments == "update")
await ApplyUpdate();
else if (toastEventArgs.Arguments == "later")
SuspendAutoUpdate = true;
}
private async void CheckForUpdatesOnSettingChanged(object sender, EventArgs e)
{
// Run an auto-update as soon as the setting gets changed to enabled
if (_checkForUpdates.Value)
await AutoUpdate();
}
private async void WindowServiceOnMainWindowOpened(object sender, EventArgs e)
{
await AutoUpdate();
}
public bool SuspendAutoUpdate { get; set; }
public async Task<bool> AutoUpdate() public async Task<bool> AutoUpdate()
{ {
if (Constants.BuildInfo.IsLocalBuild) if (Constants.BuildInfo.IsLocalBuild)
@ -114,27 +135,26 @@ namespace Artemis.UI.Services
return false; return false;
if (_windowService.IsMainWindowOpen) if (_windowService.IsMainWindowOpen)
{
await OfferUpdate(buildInfo); await OfferUpdate(buildInfo);
}
else if (_autoInstallUpdates.Value) else if (_autoInstallUpdates.Value)
{ {
// Lets go new ToastContentBuilder()
_messageService.ShowNotification( .AddText("Installing new version", AdaptiveTextStyle.Header)
"Installing new version", .AddText($"Build {buildNumberDisplay} is available, currently on {Constants.BuildInfo.BuildNumberDisplay}.")
$"Build {buildNumberDisplay} is available, currently on {Constants.BuildInfo.BuildNumberDisplay}.", .AddProgressBar(null, null, true)
PackIconKind.Update .Show();
);
await ApplyUpdate(); await ApplyUpdate();
} }
else else
{ {
// If auto-install is disabled and the window is closed, best we can do is notify the user and stop. // If auto-install is disabled and the window is closed, best we can do is notify the user and stop.
_messageService.ShowNotification( new ToastContentBuilder()
"New version available", .AddText("New version available", AdaptiveTextStyle.Header)
$"Build {buildNumberDisplay} is available, currently on {Constants.BuildInfo.BuildNumberDisplay}.", .AddText($"Build {buildNumberDisplay} is available, currently on {Constants.BuildInfo.BuildNumberDisplay}.")
PackIconKind.Update .AddButton("Update", ToastActivationType.Background, "update")
); .AddButton("Later", ToastActivationType.Background, "later")
.Show(t => t.Activated += TOnActivated);
} }
return true; return true;
@ -157,9 +177,7 @@ namespace Artemis.UI.Services
// Always update installer if it is missing ^^ // Always update installer if it is missing ^^
if (!File.Exists(installerPath)) if (!File.Exists(installerPath))
{
await UpdateInstaller(); await UpdateInstaller();
}
// Compare the creation date of the installer with the build date and update if needed // Compare the creation date of the installer with the build date and update if needed
else else
{ {
@ -226,22 +244,6 @@ namespace Artemis.UI.Services
.WithHeader("Accept", "application/vnd.github.v3+json") .WithHeader("Accept", "application/vnd.github.v3+json")
.GetJsonAsync<GitHubDifference>(); .GetJsonAsync<GitHubDifference>();
} }
#region Event handlers
private async void CheckForUpdatesOnSettingChanged(object sender, EventArgs e)
{
// Run an auto-update as soon as the setting gets changed to enabled
if (_checkForUpdates.Value)
await AutoUpdate();
}
private async void WindowServiceOnMainWindowOpened(object sender, EventArgs e)
{
await AutoUpdate();
}
#endregion
} }
public interface IUpdateService : IArtemisUIService public interface IUpdateService : IArtemisUIService

View File

@ -4,9 +4,9 @@
".NETCoreApp,Version=v5.0": { ".NETCoreApp,Version=v5.0": {
"FluentValidation": { "FluentValidation": {
"type": "Direct", "type": "Direct",
"requested": "[10.0.0, )", "requested": "[10.1.0, )",
"resolved": "10.0.0", "resolved": "10.1.0",
"contentHash": "jNFPbLjBy/bfIWx4BV/WVEsS+1OxBVf22mmSdvVa9RCHJDkNhAjbKZkxgA0s1rYNFxVn+a1fQbos95t4j/z3Zg==" "contentHash": "RxhhfY9IcEY2qUMYjoUxegInbuE5Bwll7dVLsXpiJf25g0ztmzUK+HHqtPcub1caPemhMJsC+NwjHei+NgAkvA=="
}, },
"Flurl.Http": { "Flurl.Http": {
"type": "Direct", "type": "Direct",
@ -60,6 +60,18 @@
"MaterialDesignColors": "2.0.0" "MaterialDesignColors": "2.0.0"
} }
}, },
"Microsoft.Toolkit.Uwp.Notifications": {
"type": "Direct",
"requested": "[7.0.2, )",
"resolved": "7.0.2",
"contentHash": "UWwo9Jdkk52E3zmUMoO+JC2Aix1gizCPIHtVBUON/uyzjKlnjgqoBd7zeS8HJ94Vsm2mW4OjVtPVhz3sEwEDQA==",
"dependencies": {
"Microsoft.Win32.Registry": "4.7.0",
"System.Drawing.Common": "4.7.0",
"System.Reflection.Emit": "4.7.0",
"System.ValueTuple": "4.5.0"
}
},
"Microsoft.Win32.Registry": { "Microsoft.Win32.Registry": {
"type": "Direct", "type": "Direct",
"requested": "[5.0.0, )", "requested": "[5.0.0, )",
@ -990,15 +1002,8 @@
}, },
"System.Reflection.Emit": { "System.Reflection.Emit": {
"type": "Transitive", "type": "Transitive",
"resolved": "4.3.0", "resolved": "4.7.0",
"contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", "contentHash": "VR4kk8XLKebQ4MZuKuIni/7oh+QGFmZW3qORd1GvBq/8026OpW501SzT/oypwiQl4TvT8ErnReh/NzY9u+C6wQ=="
"dependencies": {
"System.IO": "4.3.0",
"System.Reflection": "4.3.0",
"System.Reflection.Emit.ILGeneration": "4.3.0",
"System.Reflection.Primitives": "4.3.0",
"System.Runtime": "4.3.0"
}
}, },
"System.Reflection.Emit.ILGeneration": { "System.Reflection.Emit.ILGeneration": {
"type": "Transitive", "type": "Transitive",