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:
commit
7b9edb9e49
@ -57,6 +57,7 @@
|
|||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Clayerbrushes_005Cinternal/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Clayerbrushes_005Cinternal/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Clayereffects_005Cinternal/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Clayereffects_005Cinternal/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cmodules_005Cactivationrequirements/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cmodules_005Cactivationrequirements/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cmodules_005Cattributes/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cprerequisites/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cprerequisites/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cprerequisites_005Cprerequisiteaction/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cprerequisites_005Cprerequisiteaction/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cprofiling/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=plugins_005Cprofiling/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
20
src/Artemis.Core/Events/DataModelPathEventArgs.cs
Normal file
20
src/Artemis.Core/Events/DataModelPathEventArgs.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Artemis.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data about data model path related events
|
||||||
|
/// </summary>
|
||||||
|
public class DataModelPathEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
internal DataModelPathEventArgs(DataModelPath dataModelPath)
|
||||||
|
{
|
||||||
|
DataModelPath = dataModelPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the data model path this event is related to
|
||||||
|
/// </summary>
|
||||||
|
public DataModelPath DataModelPath { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -175,6 +175,8 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void Invalidate()
|
internal void Invalidate()
|
||||||
{
|
{
|
||||||
|
Target?.RemoveDataModelPath(this);
|
||||||
|
|
||||||
foreach (DataModelPathSegment dataModelPathSegment in _segments)
|
foreach (DataModelPathSegment dataModelPathSegment in _segments)
|
||||||
dataModelPathSegment.Dispose();
|
dataModelPathSegment.Dispose();
|
||||||
_segments.Clear();
|
_segments.Clear();
|
||||||
@ -187,11 +189,11 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void Initialize()
|
internal void Initialize()
|
||||||
{
|
{
|
||||||
Invalidate();
|
|
||||||
|
|
||||||
if (Target == null)
|
if (Target == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Target.AddDataModelPath(this);
|
||||||
|
|
||||||
DataModelPathSegment startSegment = new(this, "target", "target");
|
DataModelPathSegment startSegment = new(this, "target", "target");
|
||||||
startSegment.Node = _segments.AddFirst(startSegment);
|
startSegment.Node = _segments.AddFirst(startSegment);
|
||||||
|
|
||||||
@ -330,6 +332,7 @@ namespace Artemis.Core
|
|||||||
if (e.Registration.DataModel.Module.Id != Entity.DataModelId)
|
if (e.Registration.DataModel.Module.Id != Entity.DataModelId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Invalidate();
|
||||||
Target = e.Registration.DataModel;
|
Target = e.Registration.DataModel;
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
@ -339,8 +342,8 @@ namespace Artemis.Core
|
|||||||
if (e.Registration.DataModel.Module.Id != Entity.DataModelId)
|
if (e.Registration.DataModel.Module.Id != Entity.DataModelId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Target = null;
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
Target = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
@ -301,7 +301,7 @@ namespace Artemis.Core
|
|||||||
private void DynamicChildOnDynamicChildRemoved(object? sender, DynamicDataModelChildEventArgs e)
|
private void DynamicChildOnDynamicChildRemoved(object? sender, DynamicDataModelChildEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.DynamicChild.BaseValue == _dynamicDataModel)
|
if (e.DynamicChild.BaseValue == _dynamicDataModel)
|
||||||
DataModelPath.Initialize();
|
DataModelPath.Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5,6 +5,9 @@ using Artemis.Storage.Entities.Profile;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a category containing <see cref="ProfileConfigurations" />
|
||||||
|
/// </summary>
|
||||||
public class ProfileCategory : CorePropertyChanged, IStorageModel
|
public class ProfileCategory : CorePropertyChanged, IStorageModel
|
||||||
{
|
{
|
||||||
private readonly List<ProfileConfiguration> _profileConfigurations = new();
|
private readonly List<ProfileConfiguration> _profileConfigurations = new();
|
||||||
|
|||||||
@ -59,6 +59,8 @@ namespace Artemis.Core
|
|||||||
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
|
||||||
baseLayerEffect.Dispose();
|
baseLayerEffect.Dispose();
|
||||||
|
|
||||||
|
DisplayCondition?.Dispose();
|
||||||
|
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,18 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.Storage.Entities.Profile;
|
using Artemis.Storage.Entities.Profile;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
public class ProfileConfiguration : CorePropertyChanged, IStorageModel
|
/// <summary>
|
||||||
|
/// Represents the configuration of a profile, contained in a <see cref="ProfileCategory" />
|
||||||
|
/// </summary>
|
||||||
|
public class ProfileConfiguration : CorePropertyChanged, IStorageModel, IDisposable
|
||||||
{
|
{
|
||||||
private ProfileCategory _category;
|
private ProfileCategory _category;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
private bool _isMissingModule;
|
private bool _isMissingModule;
|
||||||
private bool _isSuspended;
|
private bool _isSuspended;
|
||||||
@ -140,11 +145,17 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
throw new ObjectDisposedException("ProfileConfiguration");
|
||||||
|
|
||||||
ActivationConditionMet = ActivationCondition == null || ActivationCondition.Evaluate();
|
ActivationConditionMet = ActivationCondition == null || ActivationCondition.Evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShouldBeActive(bool includeActivationCondition)
|
public bool ShouldBeActive(bool includeActivationCondition)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
throw new ObjectDisposedException("ProfileConfiguration");
|
||||||
|
|
||||||
if (Category.IsSuspended || IsSuspended || IsMissingModule)
|
if (Category.IsSuspended || IsSuspended || IsMissingModule)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -161,15 +172,32 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal void LoadModules(List<Module> enabledModules)
|
internal void LoadModules(List<Module> enabledModules)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
throw new ObjectDisposedException("ProfileConfiguration");
|
||||||
|
|
||||||
Module = enabledModules.FirstOrDefault(m => m.Id == Entity.ModuleId);
|
Module = enabledModules.FirstOrDefault(m => m.Id == Entity.ModuleId);
|
||||||
IsMissingModule = Module == null && Entity.ModuleId != null;
|
IsMissingModule = Module == null && Entity.ModuleId != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
ActivationCondition?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Implementation of IStorageModel
|
#region Implementation of IStorageModel
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Load()
|
public void Load()
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
throw new ObjectDisposedException("ProfileConfiguration");
|
||||||
|
|
||||||
Name = Entity.Name;
|
Name = Entity.Name;
|
||||||
IsSuspended = Entity.IsSuspended;
|
IsSuspended = Entity.IsSuspended;
|
||||||
ActivationBehaviour = (ActivationBehaviour) Entity.ActivationBehaviour;
|
ActivationBehaviour = (ActivationBehaviour) Entity.ActivationBehaviour;
|
||||||
@ -185,6 +213,9 @@ namespace Artemis.Core
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
throw new ObjectDisposedException("ProfileConfiguration");
|
||||||
|
|
||||||
Entity.Name = Name;
|
Entity.Name = Name;
|
||||||
Entity.IsSuspended = IsSuspended;
|
Entity.IsSuspended = IsSuspended;
|
||||||
Entity.ActivationBehaviour = (int) ActivationBehaviour;
|
Entity.ActivationBehaviour = (int) ActivationBehaviour;
|
||||||
@ -199,9 +230,7 @@ namespace Artemis.Core
|
|||||||
Entity.ActivationCondition = ActivationCondition.Entity;
|
Entity.ActivationCondition = ActivationCondition.Entity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
Entity.ActivationCondition = null;
|
Entity.ActivationCondition = null;
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsMissingModule)
|
if (!IsMissingModule)
|
||||||
Entity.ModuleId = Module?.Id;
|
Entity.ModuleId = Module?.Id;
|
||||||
|
|||||||
@ -549,11 +549,6 @@ namespace Artemis.Core
|
|||||||
else
|
else
|
||||||
LogicalLayout = DeviceEntity.LogicalLayout;
|
LogicalLayout = DeviceEntity.LogicalLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearLayout()
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Ninject;
|
||||||
|
|
||||||
namespace Artemis.Core.Modules
|
namespace Artemis.Core.Modules
|
||||||
{
|
{
|
||||||
@ -11,6 +13,8 @@ namespace Artemis.Core.Modules
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ProcessActivationRequirement : IModuleActivationRequirement
|
public class ProcessActivationRequirement : IModuleActivationRequirement
|
||||||
{
|
{
|
||||||
|
private readonly IProcessMonitorService _processMonitorService;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the <see cref="ProcessActivationRequirement" /> class
|
/// Creates a new instance of the <see cref="ProcessActivationRequirement" /> class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -18,6 +22,14 @@ namespace Artemis.Core.Modules
|
|||||||
/// <param name="location">The location of where the process must be running from (optional)</param>
|
/// <param name="location">The location of where the process must be running from (optional)</param>
|
||||||
public ProcessActivationRequirement(string? processName, string? location = null)
|
public ProcessActivationRequirement(string? processName, string? location = null)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(processName) && string.IsNullOrWhiteSpace(location))
|
||||||
|
throw new ArgumentNullException($"Atleast one {nameof(processName)} and {nameof(location)} must not be null");
|
||||||
|
|
||||||
|
// Let's not make a habit out of this :P
|
||||||
|
if (CoreService.Kernel == null)
|
||||||
|
throw new ArtemisCoreException("Cannot create a ProcessActivationRequirement before initializing the Core");
|
||||||
|
_processMonitorService = CoreService.Kernel.Get<IProcessMonitorService>();
|
||||||
|
|
||||||
ProcessName = processName;
|
ProcessName = processName;
|
||||||
Location = location;
|
Location = location;
|
||||||
}
|
}
|
||||||
@ -38,10 +50,13 @@ namespace Artemis.Core.Modules
|
|||||||
if (ProcessName == null && Location == null)
|
if (ProcessName == null && Location == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IEnumerable<Process> processes = ProcessName != null ? Process.GetProcessesByName(ProcessName).Where(p => !p.HasExited) : Process.GetProcesses().Where(p => !p.HasExited);
|
IEnumerable<Process> processes = _processMonitorService.GetRunningProcesses();
|
||||||
return Location != null
|
if (ProcessName != null)
|
||||||
? processes.Any(p => string.Equals(Path.GetDirectoryName(p.GetProcessFilename()), Location, StringComparison.CurrentCultureIgnoreCase))
|
processes = processes.Where(p => string.Equals(p.ProcessName, ProcessName, StringComparison.InvariantCultureIgnoreCase));
|
||||||
: processes.Any();
|
if (Location != null)
|
||||||
|
processes = processes.Where(p => string.Equals(Path.GetDirectoryName(p.GetProcessFilename()), Location, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
|
return processes.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Artemis.Core.DataModelExpansions
|
namespace Artemis.Core.Modules
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an attribute that marks a data model property to be ignored by the UI
|
/// Represents an attribute that marks a data model property to be ignored by the UI
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Artemis.Core.DataModelExpansions
|
namespace Artemis.Core.Modules
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents an attribute that describes a data model property
|
/// Represents an attribute that describes a data model property
|
||||||
|
|||||||
@ -1,21 +1,21 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Artemis.Core.Modules;
|
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Module = Artemis.Core.Modules.Module;
|
|
||||||
|
|
||||||
namespace Artemis.Core.DataModelExpansions
|
namespace Artemis.Core.Modules
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a data model that contains information on a game/application etc.
|
/// Represents a data model that contains information on a game/application etc.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class DataModel
|
public abstract class DataModel
|
||||||
{
|
{
|
||||||
|
private readonly HashSet<string> _activePathsHashSet = new();
|
||||||
|
private readonly List<DataModelPath> _activePaths = new();
|
||||||
private readonly Dictionary<string, DynamicChild> _dynamicChildren = new();
|
private readonly Dictionary<string, DynamicChild> _dynamicChildren = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -54,42 +54,18 @@ namespace Artemis.Core.DataModelExpansions
|
|||||||
[DataModelIgnore]
|
[DataModelIgnore]
|
||||||
public ReadOnlyDictionary<string, DynamicChild> DynamicChildren => new(_dynamicChildren);
|
public ReadOnlyDictionary<string, DynamicChild> DynamicChildren => new(_dynamicChildren);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a read-only list of <see cref="DataModelPath" />s targeting this data model
|
||||||
|
/// </summary>
|
||||||
|
public ReadOnlyCollection<DataModelPath> ActivePaths => _activePaths.AsReadOnly();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a read-only collection of all properties in this datamodel that are to be ignored
|
/// Returns a read-only collection of all properties in this datamodel that are to be ignored
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ReadOnlyCollection<PropertyInfo> GetHiddenProperties()
|
public ReadOnlyCollection<PropertyInfo> GetHiddenProperties()
|
||||||
{
|
{
|
||||||
if (Module is Module module)
|
return Module.HiddenProperties;
|
||||||
return module.HiddenProperties;
|
|
||||||
|
|
||||||
return new List<PropertyInfo>().AsReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a dynamic child has been added to this data model
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<DynamicDataModelChildEventArgs>? DynamicChildAdded;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Occurs when a dynamic child has been removed from this data model
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<DynamicDataModelChildEventArgs>? DynamicChildRemoved;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the <see cref="DynamicChildAdded" /> event
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnDynamicDataModelAdded(DynamicDataModelChildEventArgs e)
|
|
||||||
{
|
|
||||||
DynamicChildAdded?.Invoke(this, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invokes the <see cref="DynamicChildRemoved" /> event
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnDynamicDataModelRemoved(DynamicDataModelChildEventArgs e)
|
|
||||||
{
|
|
||||||
DynamicChildRemoved?.Invoke(this, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Dynamic children
|
#region Dynamic children
|
||||||
@ -277,5 +253,108 @@ namespace Artemis.Core.DataModelExpansions
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Paths
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the provided dot-separated path is in use
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to check per example: <c>MyDataModelChild.MyDataModelProperty</c></param>
|
||||||
|
/// <param name="includeChildren">
|
||||||
|
/// If <see langword="true" /> any child of the given path will return true as well; if
|
||||||
|
/// <see langword="false" /> only an exact path match returns <see langword="true" />.
|
||||||
|
/// </param>
|
||||||
|
internal bool IsPropertyInUse(string path, bool includeChildren)
|
||||||
|
{
|
||||||
|
path = path.ToUpperInvariant();
|
||||||
|
return includeChildren
|
||||||
|
? _activePathsHashSet.Any(p => p.StartsWith(path, StringComparison.Ordinal))
|
||||||
|
: _activePathsHashSet.Contains(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddDataModelPath(DataModelPath path)
|
||||||
|
{
|
||||||
|
if (_activePaths.Contains(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_activePaths.Add(path);
|
||||||
|
|
||||||
|
// Add to the hashset if this is the first path pointing
|
||||||
|
string hashPath = path.Path.ToUpperInvariant();
|
||||||
|
if (!_activePathsHashSet.Contains(hashPath))
|
||||||
|
_activePathsHashSet.Add(hashPath);
|
||||||
|
|
||||||
|
OnActivePathAdded(new DataModelPathEventArgs(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RemoveDataModelPath(DataModelPath path)
|
||||||
|
{
|
||||||
|
if (!_activePaths.Remove(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remove from the hashset if this was the last path pointing there
|
||||||
|
if (_activePaths.All(p => p.Path != path.Path))
|
||||||
|
_activePathsHashSet.Remove(path.Path.ToUpperInvariant());
|
||||||
|
|
||||||
|
OnActivePathRemoved(new DataModelPathEventArgs(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Events
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a dynamic child has been added to this data model
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<DynamicDataModelChildEventArgs>? DynamicChildAdded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a dynamic child has been removed from this data model
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<DynamicDataModelChildEventArgs>? DynamicChildRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a dynamic child has been added to this data model
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<DataModelPathEventArgs>? ActivePathAdded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a dynamic child has been removed from this data model
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<DataModelPathEventArgs>? ActivePathRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="DynamicChildAdded" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnDynamicDataModelAdded(DynamicDataModelChildEventArgs e)
|
||||||
|
{
|
||||||
|
DynamicChildAdded?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="DynamicChildRemoved" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnDynamicDataModelRemoved(DynamicDataModelChildEventArgs e)
|
||||||
|
{
|
||||||
|
DynamicChildRemoved?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ActivePathAdded" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnActivePathAdded(DataModelPathEventArgs e)
|
||||||
|
{
|
||||||
|
ActivePathAdded?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invokes the <see cref="ActivePathRemoved" /> event
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnActivePathRemoved(DataModelPathEventArgs e)
|
||||||
|
{
|
||||||
|
ActivePathRemoved?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Artemis.Core.DataModelExpansions
|
namespace Artemis.Core.Modules
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a dynamic child value with its property attribute
|
/// Represents a dynamic child value with its property attribute
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using System.Text;
|
||||||
|
|
||||||
namespace Artemis.Core.Modules
|
namespace Artemis.Core.Modules
|
||||||
{
|
{
|
||||||
@ -25,7 +25,8 @@ namespace Artemis.Core.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hide the provided property using a lambda expression, e.g. HideProperty(dm => dm.TimeDataModel.CurrentTimeUTC)
|
/// Hide the provided property using a lambda expression, e.g.
|
||||||
|
/// <c>HideProperty(dm => dm.TimeDataModel.CurrentTimeUTC)</c>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="propertyLambda">A lambda expression pointing to the property to ignore</param>
|
/// <param name="propertyLambda">A lambda expression pointing to the property to ignore</param>
|
||||||
public void HideProperty<TProperty>(Expression<Func<T, TProperty>> propertyLambda)
|
public void HideProperty<TProperty>(Expression<Func<T, TProperty>> propertyLambda)
|
||||||
@ -36,8 +37,8 @@ namespace Artemis.Core.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop hiding the provided property using a lambda expression, e.g. ShowProperty(dm =>
|
/// Stop hiding the provided property using a lambda expression, e.g.
|
||||||
/// dm.TimeDataModel.CurrentTimeUTC)
|
/// <c>ShowProperty(dm => dm.TimeDataModel.CurrentTimeUTC)</c>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="propertyLambda">A lambda expression pointing to the property to stop ignoring</param>
|
/// <param name="propertyLambda">A lambda expression pointing to the property to stop ignoring</param>
|
||||||
public void ShowProperty<TProperty>(Expression<Func<T, TProperty>> propertyLambda)
|
public void ShowProperty<TProperty>(Expression<Func<T, TProperty>> propertyLambda)
|
||||||
@ -46,6 +47,36 @@ namespace Artemis.Core.Modules
|
|||||||
HiddenPropertiesList.RemoveAll(p => p.Equals(propertyInfo));
|
HiddenPropertiesList.RemoveAll(p => p.Equals(propertyInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the provided dot-separated path is actively being used by Artemis
|
||||||
|
/// <para>Note: <see cref="IsPropertyInUse" /> is slightly faster but string-based.</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyLambda">
|
||||||
|
/// The path to check per example: <c>IsPropertyInUse(dm => dm.TimeDataModel.CurrentTimeUTC)</c>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="includeChildren">
|
||||||
|
/// If <see langword="true" /> any child of the given path will return true as well; if
|
||||||
|
/// <see langword="false" /> only an exact path match returns <see langword="true" />.
|
||||||
|
/// </param>
|
||||||
|
public bool IsPropertyInUse<TProperty>(Expression<Func<T, TProperty>> propertyLambda, bool includeChildren)
|
||||||
|
{
|
||||||
|
string path = GetMemberPath((MemberExpression) propertyLambda.Body);
|
||||||
|
return IsPropertyInUse(path, includeChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the provided dot-separated path is actively being used by Artemis
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to check per example: <c>MyDataModelChild.MyDataModelProperty</c></param>
|
||||||
|
/// <param name="includeChildren">
|
||||||
|
/// If <see langword="true" /> any child of the given path will return true as well; if
|
||||||
|
/// <see langword="false" /> only an exact path match returns <see langword="true" />.
|
||||||
|
/// </param>
|
||||||
|
public bool IsPropertyInUse(string path, bool includeChildren)
|
||||||
|
{
|
||||||
|
return DataModel.IsPropertyInUse(path, includeChildren);
|
||||||
|
}
|
||||||
|
|
||||||
internal override void InternalEnable()
|
internal override void InternalEnable()
|
||||||
{
|
{
|
||||||
DataModel = Activator.CreateInstance<T>();
|
DataModel = Activator.CreateInstance<T>();
|
||||||
@ -59,6 +90,20 @@ namespace Artemis.Core.Modules
|
|||||||
Deactivate(true);
|
Deactivate(true);
|
||||||
base.InternalDisable();
|
base.InternalDisable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetMemberPath(MemberExpression? me)
|
||||||
|
{
|
||||||
|
StringBuilder builder = new();
|
||||||
|
while (me != null)
|
||||||
|
{
|
||||||
|
builder.Insert(0, me.Member.Name);
|
||||||
|
me = me.Expression as MemberExpression;
|
||||||
|
if (me != null)
|
||||||
|
builder.Insert(0, ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -22,6 +22,8 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Action<double> action, string? name)
|
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Action<double> action, string? name)
|
||||||
{
|
{
|
||||||
|
if (CoreService.Kernel == null)
|
||||||
|
throw new ArtemisCoreException("Cannot create a TimedUpdateRegistration before initializing the Core");
|
||||||
_logger = CoreService.Kernel.Get<ILogger>();
|
_logger = CoreService.Kernel.Get<ILogger>();
|
||||||
|
|
||||||
Feature = feature;
|
Feature = feature;
|
||||||
@ -37,6 +39,8 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Func<double, Task> asyncAction, string? name)
|
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Func<double, Task> asyncAction, string? name)
|
||||||
{
|
{
|
||||||
|
if (CoreService.Kernel == null)
|
||||||
|
throw new ArtemisCoreException("Cannot create a TimedUpdateRegistration before initializing the Core");
|
||||||
_logger = CoreService.Kernel.Get<ILogger>();
|
_logger = CoreService.Kernel.Get<ILogger>();
|
||||||
|
|
||||||
Feature = feature;
|
Feature = feature;
|
||||||
|
|||||||
@ -4,7 +4,6 @@ using System.Diagnostics;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.DataModelExpansions;
|
|
||||||
using Artemis.Core.Ninject;
|
using Artemis.Core.Ninject;
|
||||||
using Artemis.Storage;
|
using Artemis.Storage;
|
||||||
using HidSharp;
|
using HidSharp;
|
||||||
@ -22,7 +21,7 @@ namespace Artemis.Core.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class CoreService : ICoreService
|
internal class CoreService : ICoreService
|
||||||
{
|
{
|
||||||
internal static IKernel Kernel = null!;
|
internal static IKernel? Kernel;
|
||||||
|
|
||||||
private readonly Stopwatch _frameStopWatch;
|
private readonly Stopwatch _frameStopWatch;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
@ -201,7 +200,7 @@ namespace Artemis.Core.Services
|
|||||||
Version? hidSharpVersion = Assembly.GetAssembly(typeof(HidDevice))!.GetName().Version;
|
Version? hidSharpVersion = Assembly.GetAssembly(typeof(HidDevice))!.GetName().Version;
|
||||||
_logger.Debug("Forcing plugins to use HidSharp {hidSharpVersion}", hidSharpVersion);
|
_logger.Debug("Forcing plugins to use HidSharp {hidSharpVersion}", hidSharpVersion);
|
||||||
|
|
||||||
DeserializationLogger.Initialize(Kernel);
|
DeserializationLogger.Initialize(Kernel!);
|
||||||
|
|
||||||
// Initialize the services
|
// Initialize the services
|
||||||
_pluginManagementService.CopyBuiltInPlugins();
|
_pluginManagementService.CopyBuiltInPlugins();
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.DataModelExpansions;
|
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core.Services
|
namespace Artemis.Core.Services
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core.Services
|
namespace Artemis.Core.Services
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using Artemis.Core.DeviceProviders;
|
using Artemis.Core.DeviceProviders;
|
||||||
using Artemis.Core.Services.Models;
|
using Artemis.Core.Services.Models;
|
||||||
using Artemis.Core.SkiaSharp;
|
using Artemis.Core.SkiaSharp;
|
||||||
@ -345,6 +346,13 @@ namespace Artemis.Core.Services
|
|||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (device.DisableDefaultLayout)
|
||||||
|
{
|
||||||
|
layout = null;
|
||||||
|
ApplyDeviceLayout(device, layout);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Look for a layout provided by the plugin
|
// Look for a layout provided by the plugin
|
||||||
layout = device.DeviceProvider.LoadLayout(device);
|
layout = device.DeviceProvider.LoadLayout(device);
|
||||||
if (layout.IsValid)
|
if (layout.IsValid)
|
||||||
@ -354,8 +362,7 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finally fall back to a default layout
|
// Finally fall back to a default layout
|
||||||
if (!device.DisableDefaultLayout)
|
layout = ArtemisLayout.GetDefaultLayout(device);
|
||||||
layout = ArtemisLayout.GetDefaultLayout(device);
|
|
||||||
ApplyDeviceLayout(device, layout);
|
ApplyDeviceLayout(device, layout);
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
@ -365,7 +372,7 @@ namespace Artemis.Core.Services
|
|||||||
if (layout == null)
|
if (layout == null)
|
||||||
{
|
{
|
||||||
if (device.Layout != null)
|
if (device.Layout != null)
|
||||||
device.ClearLayout();
|
ReloadDevice(device);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,6 +384,16 @@ namespace Artemis.Core.Services
|
|||||||
UpdateLedGroup();
|
UpdateLedGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ReloadDevice(ArtemisDevice device)
|
||||||
|
{
|
||||||
|
DeviceProvider deviceProvider = device.DeviceProvider;
|
||||||
|
|
||||||
|
// Feels bad but need to in order to get the initial LEDs back
|
||||||
|
_pluginManagementService.DisablePluginFeature(deviceProvider, false);
|
||||||
|
Thread.Sleep(500);
|
||||||
|
_pluginManagementService.EnablePluginFeature(deviceProvider, false);
|
||||||
|
}
|
||||||
|
|
||||||
public ArtemisDevice? GetDevice(IRGBDevice rgbDevice)
|
public ArtemisDevice? GetDevice(IRGBDevice rgbDevice)
|
||||||
{
|
{
|
||||||
return _devices.FirstOrDefault(d => d.RgbDevice == rgbDevice);
|
return _devices.FirstOrDefault(d => d.RgbDevice == rgbDevice);
|
||||||
|
|||||||
@ -357,6 +357,8 @@ namespace Artemis.Core.Services
|
|||||||
ProfileEntity profileEntity = _profileRepository.Get(profileConfiguration.Entity.ProfileId);
|
ProfileEntity profileEntity = _profileRepository.Get(profileConfiguration.Entity.ProfileId);
|
||||||
if (profileEntity != null)
|
if (profileEntity != null)
|
||||||
_profileRepository.Remove(profileEntity);
|
_profileRepository.Remove(profileEntity);
|
||||||
|
|
||||||
|
profileConfiguration.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveProfileCategory(ProfileCategory profileCategory)
|
public void SaveProfileCategory(ProfileCategory profileCategory)
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.DataModelExpansions;
|
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using EmbedIO;
|
using EmbedIO;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.DataModelExpansions;
|
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using EmbedIO;
|
using EmbedIO;
|
||||||
using EmbedIO.WebApi;
|
using EmbedIO.WebApi;
|
||||||
|
|||||||
@ -4,7 +4,6 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core.DataModelExpansions;
|
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using EmbedIO;
|
using EmbedIO;
|
||||||
using EmbedIO.WebApi;
|
using EmbedIO.WebApi;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using System.Threading.Tasks;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
|
|||||||
@ -272,6 +272,7 @@ namespace Artemis.UI.Shared.Input
|
|||||||
_updateTimer.Dispose();
|
_updateTimer.Dispose();
|
||||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||||
|
|
||||||
|
DataModelViewModel?.Dispose();
|
||||||
DataModelPath?.Dispose();
|
DataModelPath?.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ using System.Windows;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using MaterialDesignColors.ColorManipulation;
|
using MaterialDesignColors.ColorManipulation;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Windows.Documents;
|
using System.Windows.Documents;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
|
|||||||
@ -3,8 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ namespace Artemis.UI.Shared
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a base class for a view model that visualizes a part of the data model
|
/// Represents a base class for a view model that visualizes a part of the data model
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class DataModelVisualizationViewModel : PropertyChangedBase
|
public abstract class DataModelVisualizationViewModel : PropertyChangedBase, IDisposable
|
||||||
{
|
{
|
||||||
private const int MaxDepth = 4;
|
private const int MaxDepth = 4;
|
||||||
private BindableCollection<DataModelVisualizationViewModel> _children;
|
private BindableCollection<DataModelVisualizationViewModel> _children;
|
||||||
@ -22,6 +23,7 @@ namespace Artemis.UI.Shared
|
|||||||
private bool _isVisualizationExpanded;
|
private bool _isVisualizationExpanded;
|
||||||
private DataModelVisualizationViewModel? _parent;
|
private DataModelVisualizationViewModel? _parent;
|
||||||
private DataModelPropertyAttribute? _propertyDescription;
|
private DataModelPropertyAttribute? _propertyDescription;
|
||||||
|
private bool _populatedStaticChildren;
|
||||||
|
|
||||||
internal DataModelVisualizationViewModel(DataModel? dataModel, DataModelVisualizationViewModel? parent, DataModelPath? dataModelPath)
|
internal DataModelVisualizationViewModel(DataModel? dataModel, DataModelVisualizationViewModel? parent, DataModelPath? dataModelPath)
|
||||||
{
|
{
|
||||||
@ -206,21 +208,26 @@ namespace Artemis.UI.Shared
|
|||||||
if (modelType == null)
|
if (modelType == null)
|
||||||
throw new ArtemisSharedUIException("Failed to populate data model visualization properties, couldn't get a property type");
|
throw new ArtemisSharedUIException("Failed to populate data model visualization properties, couldn't get a property type");
|
||||||
|
|
||||||
// Add missing static children
|
// Add missing static children only once, they're static after all
|
||||||
foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(t => t.MetadataToken))
|
if (!_populatedStaticChildren)
|
||||||
{
|
{
|
||||||
string childPath = AppendToPath(propertyInfo.Name);
|
foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(t => t.MetadataToken))
|
||||||
if (Children.Any(c => c.Path != null && c.Path.Equals(childPath)))
|
{
|
||||||
continue;
|
string childPath = AppendToPath(propertyInfo.Name);
|
||||||
if (propertyInfo.GetCustomAttribute<DataModelIgnoreAttribute>() != null)
|
if (Children.Any(c => c.Path != null && c.Path.Equals(childPath)))
|
||||||
continue;
|
continue;
|
||||||
MethodInfo? getMethod = propertyInfo.GetGetMethod();
|
if (propertyInfo.GetCustomAttribute<DataModelIgnoreAttribute>() != null)
|
||||||
if (getMethod == null || getMethod.GetParameters().Any())
|
continue;
|
||||||
continue;
|
MethodInfo? getMethod = propertyInfo.GetGetMethod();
|
||||||
|
if (getMethod == null || getMethod.GetParameters().Any())
|
||||||
|
continue;
|
||||||
|
|
||||||
DataModelVisualizationViewModel? child = CreateChild(dataModelUIService, childPath, GetChildDepth());
|
DataModelVisualizationViewModel? child = CreateChild(dataModelUIService, childPath, GetChildDepth());
|
||||||
if (child != null)
|
if (child != null)
|
||||||
Children.Add(child);
|
Children.Add(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
_populatedStaticChildren = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove static children that should be hidden
|
// Remove static children that should be hidden
|
||||||
@ -302,7 +309,14 @@ namespace Artemis.UI.Shared
|
|||||||
|
|
||||||
private string AppendToPath(string toAppend)
|
private string AppendToPath(string toAppend)
|
||||||
{
|
{
|
||||||
return !string.IsNullOrEmpty(Path) ? $"{Path}.{toAppend}" : toAppend;
|
if (string.IsNullOrEmpty(Path))
|
||||||
|
return toAppend;
|
||||||
|
|
||||||
|
StringBuilder builder = new();
|
||||||
|
builder.Append(Path);
|
||||||
|
builder.Append(".");
|
||||||
|
builder.Append(toAppend);
|
||||||
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RequestUpdate()
|
private void RequestUpdate()
|
||||||
@ -327,5 +341,33 @@ namespace Artemis.UI.Shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">
|
||||||
|
/// <see langword="true" /> to release both managed and unmanaged resources;
|
||||||
|
/// <see langword="false" /> to release only unmanaged resources.
|
||||||
|
/// </param>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
DataModelPath?.Dispose();
|
||||||
|
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
|
||||||
|
dataModelVisualizationViewModel.Dispose(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Artemis.Core.DataModelExpansions;
|
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Input;
|
using Artemis.UI.Shared.Input;
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.DataModelExpansions;
|
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Shared.DefaultTypes.DataModel.Display;
|
using Artemis.UI.Shared.DefaultTypes.DataModel.Display;
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.DataModelExpansions;
|
|
||||||
using Artemis.Core.Modules;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared.Input;
|
using Artemis.UI.Shared.Input;
|
||||||
|
|
||||||
|
|||||||
@ -7,10 +7,8 @@ using System.Net.Http;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Screens;
|
|
||||||
using Artemis.UI.Utilities;
|
using Artemis.UI.Utilities;
|
||||||
using Ninject;
|
using Ninject;
|
||||||
using Ookii.Dialogs.Wpf;
|
using Ookii.Dialogs.Wpf;
|
||||||
@ -44,30 +42,82 @@ namespace Artemis.UI
|
|||||||
if (createdNew)
|
if (createdNew)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try
|
return RemoteFocus();
|
||||||
{
|
|
||||||
// Blocking is required here otherwise Artemis shuts down before the remote call gets a chance to finish
|
|
||||||
RemoteFocus().GetAwaiter().GetResult();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// Not much could go wrong here but this code runs so early it'll crash if something does go wrong
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RemoteFocus()
|
public void DisplayException(Exception e)
|
||||||
|
{
|
||||||
|
using TaskDialog dialog = new();
|
||||||
|
AssemblyInformationalVersionAttribute versionAttribute = typeof(ApplicationStateManager).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
|
||||||
|
dialog.WindowTitle = $"Artemis {versionAttribute?.InformationalVersion} build {Constants.BuildInfo.BuildNumberDisplay}";
|
||||||
|
dialog.MainInstruction = "Unfortunately Artemis ran into an unhandled exception and cannot continue.";
|
||||||
|
dialog.Content = e.Message;
|
||||||
|
dialog.ExpandedInformation = e.StackTrace.Trim();
|
||||||
|
|
||||||
|
dialog.CollapsedControlText = "Show stack trace";
|
||||||
|
dialog.ExpandedControlText = "Hide stack trace";
|
||||||
|
|
||||||
|
dialog.Footer = "If this keeps happening check out the <a href=\"https://wiki.artemis-rgb.com\">wiki</a> or hit us up on <a href=\"https://discord.gg/S3MVaC9\">Discord</a>.";
|
||||||
|
dialog.FooterIcon = TaskDialogIcon.Error;
|
||||||
|
dialog.EnableHyperlinks = true;
|
||||||
|
dialog.HyperlinkClicked += OpenHyperlink;
|
||||||
|
|
||||||
|
TaskDialogButton copyButton = new("Copy stack trace");
|
||||||
|
TaskDialogButton closeButton = new("Close") {Default = true};
|
||||||
|
dialog.Buttons.Add(copyButton);
|
||||||
|
dialog.Buttons.Add(closeButton);
|
||||||
|
dialog.ButtonClicked += (_, args) =>
|
||||||
|
{
|
||||||
|
if (args.Item == copyButton)
|
||||||
|
{
|
||||||
|
Clipboard.SetText(e.ToString());
|
||||||
|
args.Cancel = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog.ShowDialog(Application.Current.MainWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool RemoteFocus()
|
||||||
{
|
{
|
||||||
// At this point we cannot read the database yet to retrieve the web server port.
|
// At this point we cannot read the database yet to retrieve the web server port.
|
||||||
// Instead use the method external applications should use as well.
|
// Instead use the method external applications should use as well.
|
||||||
if (!File.Exists(Path.Combine(Constants.DataFolder, "webserver.txt")))
|
if (!File.Exists(Path.Combine(Constants.DataFolder, "webserver.txt")))
|
||||||
return;
|
{
|
||||||
|
KillOtherInstances();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
string url = await File.ReadAllTextAsync(Path.Combine(Constants.DataFolder, "webserver.txt"));
|
string url = File.ReadAllText(Path.Combine(Constants.DataFolder, "webserver.txt"));
|
||||||
using HttpClient client = new();
|
using HttpClient client = new();
|
||||||
await client.PostAsync(url + "remote/bring-to-foreground", null!);
|
try
|
||||||
|
{
|
||||||
|
HttpResponseMessage httpResponseMessage = client.Send(new HttpRequestMessage(HttpMethod.Post, url + "remote/bring-to-foreground"));
|
||||||
|
httpResponseMessage.EnsureSuccessStatusCode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
KillOtherInstances();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void KillOtherInstances()
|
||||||
|
{
|
||||||
|
// Kill everything else heh
|
||||||
|
List<Process> processes = Process.GetProcessesByName("Artemis.UI").Where(p => p.Id != Process.GetCurrentProcess().Id).ToList();
|
||||||
|
foreach (Process process in processes)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
process.Kill(true);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UtilitiesOnRestartRequested(object sender, RestartEventArgs e)
|
private void UtilitiesOnRestartRequested(object sender, RestartEventArgs e)
|
||||||
@ -134,39 +184,6 @@ namespace Artemis.UI
|
|||||||
Execute.OnUIThread(() => Application.Current.Shutdown());
|
Execute.OnUIThread(() => Application.Current.Shutdown());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisplayException(Exception e)
|
|
||||||
{
|
|
||||||
using TaskDialog dialog = new();
|
|
||||||
AssemblyInformationalVersionAttribute versionAttribute = typeof(ApplicationStateManager).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
|
|
||||||
dialog.WindowTitle = $"Artemis {versionAttribute?.InformationalVersion} build {Constants.BuildInfo.BuildNumberDisplay}";
|
|
||||||
dialog.MainInstruction = "Unfortunately Artemis ran into an unhandled exception and cannot continue.";
|
|
||||||
dialog.Content = e.Message;
|
|
||||||
dialog.ExpandedInformation = e.StackTrace.Trim();
|
|
||||||
|
|
||||||
dialog.CollapsedControlText = "Show stack trace";
|
|
||||||
dialog.ExpandedControlText = "Hide stack trace";
|
|
||||||
|
|
||||||
dialog.Footer = "If this keeps happening check out the <a href=\"https://wiki.artemis-rgb.com\">wiki</a> or hit us up on <a href=\"https://discord.gg/S3MVaC9\">Discord</a>.";
|
|
||||||
dialog.FooterIcon = TaskDialogIcon.Error;
|
|
||||||
dialog.EnableHyperlinks = true;
|
|
||||||
dialog.HyperlinkClicked += OpenHyperlink;
|
|
||||||
|
|
||||||
TaskDialogButton copyButton = new("Copy stack trace");
|
|
||||||
TaskDialogButton closeButton = new("Close") {Default = true};
|
|
||||||
dialog.Buttons.Add(copyButton);
|
|
||||||
dialog.Buttons.Add(closeButton);
|
|
||||||
dialog.ButtonClicked += (_, args) =>
|
|
||||||
{
|
|
||||||
if (args.Item == copyButton)
|
|
||||||
{
|
|
||||||
Clipboard.SetText(e.ToString());
|
|
||||||
args.Cancel = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
dialog.ShowDialog(Application.Current.MainWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OpenHyperlink(object sender, HyperlinkClickedEventArgs e)
|
private void OpenHyperlink(object sender, HyperlinkClickedEventArgs e)
|
||||||
{
|
{
|
||||||
ProcessStartInfo processInfo = new()
|
ProcessStartInfo processInfo = new()
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
namespace Artemis.UI.DefaultTypes.DataModel.Input
|
namespace Artemis.UI.DefaultTypes.DataModel.Input
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
namespace Artemis.UI.DefaultTypes.DataModel.Input
|
namespace Artemis.UI.DefaultTypes.DataModel.Input
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
namespace Artemis.UI.DefaultTypes.DataModel.Input
|
namespace Artemis.UI.DefaultTypes.DataModel.Input
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.Modules;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
namespace Artemis.UI.DefaultTypes.DataModel.Input
|
namespace Artemis.UI.DefaultTypes.DataModel.Input
|
||||||
|
|||||||
@ -9,6 +9,7 @@ using System.Windows.Media;
|
|||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.LayerEffects;
|
using Artemis.Core.LayerEffects;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects;
|
||||||
@ -220,7 +221,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
|
|
||||||
private void SelectedProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
|
private void SelectedProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
|
||||||
{
|
{
|
||||||
PopulateProperties(e.RenderProfileElement);
|
Execute.PostToUIThread(() => PopulateProperties(e.RenderProfileElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e)
|
private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e)
|
||||||
@ -347,7 +348,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
.ToList();
|
.ToList();
|
||||||
// Order the effects
|
// Order the effects
|
||||||
List<LayerPropertyGroupViewModel> effectProperties = Items
|
List<LayerPropertyGroupViewModel> effectProperties = Items
|
||||||
.Where(l => l.TreeGroupViewModel.GroupType == LayerEffectRoot)
|
.Where(l => l.TreeGroupViewModel.GroupType == LayerEffectRoot && l.LayerPropertyGroup.LayerEffect != null)
|
||||||
.OrderBy(l => l.LayerPropertyGroup.LayerEffect.Order)
|
.OrderBy(l => l.LayerPropertyGroup.LayerEffect.Order)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -355,14 +356,16 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
for (int index = 0; index < nonEffectProperties.Count; index++)
|
for (int index = 0; index < nonEffectProperties.Count; index++)
|
||||||
{
|
{
|
||||||
LayerPropertyGroupViewModel layerPropertyGroupViewModel = nonEffectProperties[index];
|
LayerPropertyGroupViewModel layerPropertyGroupViewModel = nonEffectProperties[index];
|
||||||
((BindableCollection<LayerPropertyGroupViewModel>) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index);
|
if (Items.IndexOf(layerPropertyGroupViewModel) != index)
|
||||||
|
((BindableCollection<LayerPropertyGroupViewModel>) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the effect properties after, sorted by their order
|
// Put the effect properties after, sorted by their order
|
||||||
for (int index = 0; index < effectProperties.Count; index++)
|
for (int index = 0; index < effectProperties.Count; index++)
|
||||||
{
|
{
|
||||||
LayerPropertyGroupViewModel layerPropertyGroupViewModel = effectProperties[index];
|
LayerPropertyGroupViewModel layerPropertyGroupViewModel = effectProperties[index];
|
||||||
((BindableCollection<LayerPropertyGroupViewModel>) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count);
|
if (Items.IndexOf(layerPropertyGroupViewModel) != index + nonEffectProperties.Count)
|
||||||
|
((BindableCollection<LayerPropertyGroupViewModel>) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -637,7 +640,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
|
|||||||
public void TimelineJump(object sender, MouseButtonEventArgs e)
|
public void TimelineJump(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
// Get the parent grid, need that for our position
|
// Get the parent grid, need that for our position
|
||||||
IInputElement parent = (IInputElement)VisualTreeHelper.GetParent((DependencyObject)sender);
|
IInputElement parent = (IInputElement) VisualTreeHelper.GetParent((DependencyObject) sender);
|
||||||
double x = Math.Max(0, e.GetPosition(parent).X);
|
double x = Math.Max(0, e.GetPosition(parent).X);
|
||||||
TimeSpan newTime = TimeSpan.FromSeconds(x / ProfileEditorService.PixelsPerSecond);
|
TimeSpan newTime = TimeSpan.FromSeconds(x / ProfileEditorService.PixelsPerSecond);
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,15 @@
|
|||||||
d:DataContext="{d:DesignInstance {x:Type profileTree1:ProfileTreeViewModel}}">
|
d:DataContext="{d:DesignInstance {x:Type profileTree1:ProfileTreeViewModel}}">
|
||||||
<materialDesign:DialogHost IsTabStop="False" Focusable="False" Identifier="ProfileTreeDialog" DialogTheme="Inherit">
|
<materialDesign:DialogHost IsTabStop="False" Focusable="False" Identifier="ProfileTreeDialog" DialogTheme="Inherit">
|
||||||
<Grid>
|
<Grid>
|
||||||
|
<Grid.Resources>
|
||||||
|
<DataTemplate x:Key="ElementDragTemplate" DataType="{x:Type treeItem:TreeItemViewModel}">
|
||||||
|
<Border Background="{DynamicResource MaterialDesignTextFieldBoxHoverBackground}"
|
||||||
|
Padding="10"
|
||||||
|
CornerRadius="4">
|
||||||
|
<TextBlock Text="{Binding ProfileElement.Name}" VerticalAlignment="Center" Foreground="{DynamicResource MaterialDesignBody}" />
|
||||||
|
</Border>
|
||||||
|
</DataTemplate>
|
||||||
|
</Grid.Resources>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
@ -33,7 +42,10 @@
|
|||||||
dd:DragDrop.IsDragSource="True"
|
dd:DragDrop.IsDragSource="True"
|
||||||
dd:DragDrop.IsDropTarget="True"
|
dd:DragDrop.IsDropTarget="True"
|
||||||
dd:DragDrop.DropHandler="{Binding}"
|
dd:DragDrop.DropHandler="{Binding}"
|
||||||
ContextMenuOpening="{s:Action ContextMenuOpening}">
|
dd:DragDrop.DragAdornerTemplate="{StaticResource ElementDragTemplate}"
|
||||||
|
ContextMenuOpening="{s:Action ContextMenuOpening}"
|
||||||
|
PreviewMouseDown="{s:Action TreeViewPreviewMouseDown}"
|
||||||
|
PreviewMouseUp="{s:Action TreeViewPreviewMouseUp}">
|
||||||
<TreeView.InputBindings>
|
<TreeView.InputBindings>
|
||||||
<KeyBinding Key="F2" Command="{s:Action RenameElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
<KeyBinding Key="F2" Command="{s:Action RenameElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
||||||
<KeyBinding Key="Delete" Command="{s:Action DeleteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
<KeyBinding Key="Delete" Command="{s:Action DeleteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem;
|
using Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem;
|
||||||
@ -15,6 +16,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
{
|
{
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
|
||||||
|
private bool _draggingTreeView;
|
||||||
private TreeItemViewModel _selectedTreeItem;
|
private TreeItemViewModel _selectedTreeItem;
|
||||||
private bool _updatingTree;
|
private bool _updatingTree;
|
||||||
|
|
||||||
@ -31,18 +33,24 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
get => _selectedTreeItem;
|
get => _selectedTreeItem;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (_updatingTree) return;
|
if (!_updatingTree && SetAndNotify(ref _selectedTreeItem, value) && !_draggingTreeView)
|
||||||
if (!SetAndNotify(ref _selectedTreeItem, value)) return;
|
ApplySelectedTreeItem();
|
||||||
|
|
||||||
if (value != null && value.ProfileElement is RenderProfileElement renderElement)
|
|
||||||
_profileEditorService.ChangeSelectedProfileElement(renderElement);
|
|
||||||
else
|
|
||||||
_profileEditorService.ChangeSelectedProfileElement(null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement();
|
public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement();
|
||||||
|
|
||||||
|
public void TreeViewPreviewMouseDown(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
_draggingTreeView = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TreeViewPreviewMouseUp(object sender, MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
_draggingTreeView = false;
|
||||||
|
ApplySelectedTreeItem();
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnInitialActivate()
|
protected override void OnInitialActivate()
|
||||||
{
|
{
|
||||||
Subscribe();
|
Subscribe();
|
||||||
@ -55,6 +63,14 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
|
|||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ApplySelectedTreeItem()
|
||||||
|
{
|
||||||
|
if (_selectedTreeItem != null && _selectedTreeItem.ProfileElement is RenderProfileElement renderElement)
|
||||||
|
_profileEditorService.ChangeSelectedProfileElement(renderElement);
|
||||||
|
else
|
||||||
|
_profileEditorService.ChangeSelectedProfileElement(null);
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateRootFolderViewModel()
|
private void CreateRootFolderViewModel()
|
||||||
{
|
{
|
||||||
_updatingTree = true;
|
_updatingTree = true;
|
||||||
|
|||||||
@ -184,6 +184,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
else
|
else
|
||||||
newSelection = ProfileElement.Parent;
|
newSelection = ProfileElement.Parent;
|
||||||
}
|
}
|
||||||
|
_profileEditorService.ChangeSelectedProfileElement(newSelection as RenderProfileElement);
|
||||||
|
|
||||||
// Farewell, cruel world
|
// Farewell, cruel world
|
||||||
TreeItemViewModel parent = (TreeItemViewModel) Parent;
|
TreeItemViewModel parent = (TreeItemViewModel) Parent;
|
||||||
@ -191,7 +192,6 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
|
|||||||
parent.RemoveExistingElement(this);
|
parent.RemoveExistingElement(this);
|
||||||
|
|
||||||
_profileEditorService.SaveSelectedProfileConfiguration();
|
_profileEditorService.SaveSelectedProfileConfiguration();
|
||||||
_profileEditorService.ChangeSelectedProfileElement(newSelection as RenderProfileElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DuplicateElement()
|
public void DuplicateElement()
|
||||||
|
|||||||
@ -87,7 +87,7 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
protected override void OnClose()
|
protected override void OnClose()
|
||||||
{
|
{
|
||||||
_updateTimer.Dispose();
|
_updateTimer.Dispose();
|
||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -109,6 +109,9 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
|||||||
{
|
{
|
||||||
_updateTimer.Stop();
|
_updateTimer.Stop();
|
||||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||||
|
MainDataModel?.Dispose();
|
||||||
|
MainDataModel = null;
|
||||||
|
|
||||||
_pluginManagementService.PluginFeatureEnabled -= OnPluginFeatureToggled;
|
_pluginManagementService.PluginFeatureEnabled -= OnPluginFeatureToggled;
|
||||||
_pluginManagementService.PluginFeatureDisabled -= OnPluginFeatureToggled;
|
_pluginManagementService.PluginFeatureDisabled -= OnPluginFeatureToggled;
|
||||||
|
|
||||||
|
|||||||
@ -25,9 +25,11 @@ namespace Artemis.UI.Screens.Settings.Device
|
|||||||
private readonly ICoreService _coreService;
|
private readonly ICoreService _coreService;
|
||||||
private readonly IDeviceService _deviceService;
|
private readonly IDeviceService _deviceService;
|
||||||
private readonly IDialogService _dialogService;
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly IDeviceDebugVmFactory _factory;
|
||||||
private readonly IRgbService _rgbService;
|
private readonly IRgbService _rgbService;
|
||||||
private SnackbarMessageQueue _deviceMessageQueue;
|
private SnackbarMessageQueue _deviceMessageQueue;
|
||||||
private BindableCollection<ArtemisLed> _selectedLeds;
|
private BindableCollection<ArtemisLed> _selectedLeds;
|
||||||
|
private ArtemisDevice _device;
|
||||||
|
|
||||||
public DeviceDialogViewModel(ArtemisDevice device,
|
public DeviceDialogViewModel(ArtemisDevice device,
|
||||||
ICoreService coreService,
|
ICoreService coreService,
|
||||||
@ -40,22 +42,46 @@ namespace Artemis.UI.Screens.Settings.Device
|
|||||||
_deviceService = deviceService;
|
_deviceService = deviceService;
|
||||||
_rgbService = rgbService;
|
_rgbService = rgbService;
|
||||||
_dialogService = dialogService;
|
_dialogService = dialogService;
|
||||||
|
_factory = factory;
|
||||||
|
|
||||||
Device = device;
|
|
||||||
PanZoomViewModel = new PanZoomViewModel();
|
PanZoomViewModel = new PanZoomViewModel();
|
||||||
SelectedLeds = new BindableCollection<ArtemisLed>();
|
SelectedLeds = new BindableCollection<ArtemisLed>();
|
||||||
|
|
||||||
Items.Add(factory.DevicePropertiesTabViewModel(device));
|
Initialize(device);
|
||||||
if (device.DeviceType == RGBDeviceType.Keyboard)
|
}
|
||||||
Items.Add(factory.InputMappingsTabViewModel(device));
|
|
||||||
Items.Add(factory.DeviceInfoTabViewModel(device));
|
private void Initialize(ArtemisDevice device)
|
||||||
Items.Add(factory.DeviceLedsTabViewModel(device));
|
{
|
||||||
|
if (SelectedLeds.Any())
|
||||||
ActiveItem = Items.First();
|
SelectedLeds.Clear();
|
||||||
DisplayName = $"{device.RgbDevice.DeviceInfo.Model} | Artemis";
|
|
||||||
|
if (Device != null)
|
||||||
|
Device.DeviceUpdated -= DeviceOnDeviceUpdated;
|
||||||
|
Device = device;
|
||||||
|
Device.DeviceUpdated += DeviceOnDeviceUpdated;
|
||||||
|
|
||||||
|
int activeTabIndex = 0;
|
||||||
|
if (Items.Any())
|
||||||
|
{
|
||||||
|
activeTabIndex = Items.IndexOf(ActiveItem);
|
||||||
|
Items.Clear();
|
||||||
|
}
|
||||||
|
Items.Add(_factory.DevicePropertiesTabViewModel(Device));
|
||||||
|
if (Device.DeviceType == RGBDeviceType.Keyboard)
|
||||||
|
Items.Add(_factory.InputMappingsTabViewModel(Device));
|
||||||
|
Items.Add(_factory.DeviceInfoTabViewModel(Device));
|
||||||
|
Items.Add(_factory.DeviceLedsTabViewModel(Device));
|
||||||
|
|
||||||
|
ActiveItem = Items[activeTabIndex];
|
||||||
|
DisplayName = $"{Device.RgbDevice.DeviceInfo.Model} | Artemis";
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArtemisDevice Device
|
||||||
|
{
|
||||||
|
get => _device;
|
||||||
|
set => SetAndNotify(ref _device, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisDevice Device { get; }
|
|
||||||
public PanZoomViewModel PanZoomViewModel { get; }
|
public PanZoomViewModel PanZoomViewModel { get; }
|
||||||
|
|
||||||
public SnackbarMessageQueue DeviceMessageQueue
|
public SnackbarMessageQueue DeviceMessageQueue
|
||||||
@ -84,14 +110,21 @@ namespace Artemis.UI.Screens.Settings.Device
|
|||||||
protected override void OnInitialActivate()
|
protected override void OnInitialActivate()
|
||||||
{
|
{
|
||||||
_coreService.FrameRendering += CoreServiceOnFrameRendering;
|
_coreService.FrameRendering += CoreServiceOnFrameRendering;
|
||||||
|
_rgbService.DeviceAdded += RgbServiceOnDeviceAdded;
|
||||||
DeviceMessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(5));
|
DeviceMessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(5));
|
||||||
Device.DeviceUpdated += DeviceOnDeviceUpdated;
|
|
||||||
base.OnInitialActivate();
|
base.OnInitialActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RgbServiceOnDeviceAdded(object sender, DeviceEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Device != Device && e.Device.Identifier == Device.Identifier)
|
||||||
|
Execute.OnUIThread(() => Initialize(e.Device));
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnClose()
|
protected override void OnClose()
|
||||||
{
|
{
|
||||||
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
|
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
|
||||||
|
_rgbService.DeviceAdded -= RgbServiceOnDeviceAdded;
|
||||||
Device.DeviceUpdated -= DeviceOnDeviceUpdated;
|
Device.DeviceUpdated -= DeviceOnDeviceUpdated;
|
||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -202,12 +202,12 @@
|
|||||||
The device layout is used to determine the position of LEDs and to create the visual representation of the device you see on the left side of this window.
|
The device layout is used to determine the position of LEDs and to create the visual representation of the device you see on the left side of this window.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
|
|
||||||
<CheckBox Margin="0 0 0 5" Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding UseDefaultLayout}">
|
<CheckBox Margin="0 0 0 5" Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding Device.DisableDefaultLayout, Delay=300}">
|
||||||
<CheckBox.Content>
|
<CheckBox.Content>
|
||||||
<TextBlock Margin="0 -5 0 0">
|
<TextBlock Margin="0 -5 0 0">
|
||||||
Use default layout if needed
|
Don't load default layout
|
||||||
<materialDesign:PackIcon Kind="HelpCircle"
|
<materialDesign:PackIcon Kind="HelpCircle"
|
||||||
ToolTip="If there is no built-in layout and no custom layout, with this enabled Artemis will fall back to the default layout of this device type." />
|
ToolTip="With this enabled Artemis will not load a layout for this device unless you specifically provide one." />
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</CheckBox.Content>
|
</CheckBox.Content>
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
|||||||
@ -134,16 +134,6 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
|
|||||||
set => SetCategory(DeviceCategory.Peripherals, value);
|
set => SetCategory(DeviceCategory.Peripherals, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UseDefaultLayout
|
|
||||||
{
|
|
||||||
get => !Device.DisableDefaultLayout;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Device.DisableDefaultLayout = !value;
|
|
||||||
NotifyOfPropertyChange(nameof(UseDefaultLayout));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyScaling()
|
public void ApplyScaling()
|
||||||
{
|
{
|
||||||
Device.RedScale = RedScale / 100f;
|
Device.RedScale = RedScale / 100f;
|
||||||
@ -266,7 +256,9 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
|
|||||||
private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout))
|
if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout))
|
||||||
_rgbService.ApplyBestDeviceLayout(Device);
|
{
|
||||||
|
Task.Run(() => _rgbService.ApplyBestDeviceLayout(Device));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFrameRendering(object sender, FrameRenderingEventArgs e)
|
private void OnFrameRendering(object sender, FrameRenderingEventArgs e)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
@ -10,9 +11,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
|||||||
{
|
{
|
||||||
public class DeviceSettingsTabViewModel : Conductor<DeviceSettingsViewModel>.Collection.AllActive
|
public class DeviceSettingsTabViewModel : Conductor<DeviceSettingsViewModel>.Collection.AllActive
|
||||||
{
|
{
|
||||||
private readonly ISettingsVmFactory _settingsVmFactory;
|
|
||||||
private readonly IRgbService _rgbService;
|
|
||||||
private readonly IDialogService _dialogService;
|
private readonly IDialogService _dialogService;
|
||||||
|
private readonly IRgbService _rgbService;
|
||||||
|
private readonly ISettingsVmFactory _settingsVmFactory;
|
||||||
private bool _confirmedDisable;
|
private bool _confirmedDisable;
|
||||||
|
|
||||||
public DeviceSettingsTabViewModel(IRgbService rgbService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
|
public DeviceSettingsTabViewModel(IRgbService rgbService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
|
||||||
@ -24,28 +25,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
|||||||
_settingsVmFactory = settingsVmFactory;
|
_settingsVmFactory = settingsVmFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Overrides of AllActive
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void OnActivate()
|
|
||||||
{
|
|
||||||
// Take it off the UI thread to avoid freezing on tab change
|
|
||||||
Task.Run(async () =>
|
|
||||||
{
|
|
||||||
if (Items.Any())
|
|
||||||
Items.Clear();
|
|
||||||
|
|
||||||
await Task.Delay(200);
|
|
||||||
|
|
||||||
List<DeviceSettingsViewModel> instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
|
|
||||||
foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances)
|
|
||||||
Items.Add(deviceSettingsViewModel);
|
|
||||||
});
|
|
||||||
base.OnActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public async Task<bool> ShowDeviceDisableDialog()
|
public async Task<bool> ShowDeviceDisableDialog()
|
||||||
{
|
{
|
||||||
if (_confirmedDisable)
|
if (_confirmedDisable)
|
||||||
@ -61,5 +40,49 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
|
|||||||
|
|
||||||
return confirmed;
|
return confirmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RgbServiceOnDeviceRemoved(object sender, DeviceEventArgs e)
|
||||||
|
{
|
||||||
|
DeviceSettingsViewModel viewModel = Items.FirstOrDefault(i => i.Device == e.Device);
|
||||||
|
if (viewModel != null)
|
||||||
|
Items.Remove(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RgbServiceOnDeviceAdded(object sender, DeviceEventArgs e)
|
||||||
|
{
|
||||||
|
Items.Add(_settingsVmFactory.CreateDeviceSettingsViewModel(e.Device));
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Overrides of AllActive
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnActivate()
|
||||||
|
{
|
||||||
|
_rgbService.DeviceAdded += RgbServiceOnDeviceAdded;
|
||||||
|
_rgbService.DeviceRemoved += RgbServiceOnDeviceRemoved;
|
||||||
|
// Take it off the UI thread to avoid freezing on tab change
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
if (Items.Any())
|
||||||
|
Items.Clear();
|
||||||
|
|
||||||
|
await Task.Delay(200);
|
||||||
|
|
||||||
|
List<DeviceSettingsViewModel> instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
|
||||||
|
foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances)
|
||||||
|
Items.Add(deviceSettingsViewModel);
|
||||||
|
});
|
||||||
|
base.OnActivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnClose()
|
||||||
|
{
|
||||||
|
_rgbService.DeviceAdded -= RgbServiceOnDeviceAdded;
|
||||||
|
_rgbService.DeviceRemoved -= RgbServiceOnDeviceRemoved;
|
||||||
|
base.OnClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,27 +218,6 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
||||||
|
|
||||||
<Grid>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition />
|
|
||||||
<RowDefinition />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<StackPanel Grid.Column="0">
|
|
||||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Automatically install updates</TextBlock>
|
|
||||||
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
|
|
||||||
If enabled updates are installed automatically without asking first.
|
|
||||||
</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
|
|
||||||
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding AutoInstallUpdates}" IsEnabled="{Binding CheckForUpdates}" />
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
|
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition />
|
<RowDefinition />
|
||||||
|
|||||||
@ -158,20 +158,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
|
|||||||
_settingsService.GetSetting("UI.CheckForUpdates", true).Value = value;
|
_settingsService.GetSetting("UI.CheckForUpdates", true).Value = value;
|
||||||
_settingsService.GetSetting("UI.CheckForUpdates", true).Save();
|
_settingsService.GetSetting("UI.CheckForUpdates", true).Save();
|
||||||
NotifyOfPropertyChange(nameof(CheckForUpdates));
|
NotifyOfPropertyChange(nameof(CheckForUpdates));
|
||||||
|
|
||||||
if (!value)
|
|
||||||
AutoInstallUpdates = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AutoInstallUpdates
|
|
||||||
{
|
|
||||||
get => _settingsService.GetSetting("UI.AutoInstallUpdates", false).Value;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_settingsService.GetSetting("UI.AutoInstallUpdates", false).Value = value;
|
|
||||||
_settingsService.GetSetting("UI.AutoInstallUpdates", false).Save();
|
|
||||||
NotifyOfPropertyChange(nameof(AutoInstallUpdates));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -91,14 +91,10 @@
|
|||||||
<StackPanel>
|
<StackPanel>
|
||||||
<StackPanel.Resources>
|
<StackPanel.Resources>
|
||||||
<DataTemplate x:Key="CategoryDragTemplate" DataType="{x:Type sidebar:SidebarCategoryViewModel}">
|
<DataTemplate x:Key="CategoryDragTemplate" DataType="{x:Type sidebar:SidebarCategoryViewModel}">
|
||||||
<DataTemplate.Resources>
|
|
||||||
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
|
||||||
</DataTemplate.Resources>
|
|
||||||
<Border Background="{DynamicResource MaterialDesignTextFieldBoxHoverBackground}"
|
<Border Background="{DynamicResource MaterialDesignTextFieldBoxHoverBackground}"
|
||||||
Padding="10"
|
Padding="10"
|
||||||
CornerRadius="4"
|
CornerRadius="4">
|
||||||
Visibility="{Binding Path=ProfileCategory, FallbackValue=null, Converter={StaticResource NullToVisibilityConverter}}">
|
<TextBlock Text="{Binding ProfileCategory.Name}" VerticalAlignment="Center" Foreground="{DynamicResource MaterialDesignBody}" />
|
||||||
<TextBlock Text="{Binding ProfileCategory.Name,TargetNullValue='Oops, I am missing'}" VerticalAlignment="Center" Foreground="{DynamicResource MaterialDesignBody}" />
|
|
||||||
</Border>
|
</Border>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</StackPanel.Resources>
|
</StackPanel.Resources>
|
||||||
|
|||||||
@ -69,7 +69,7 @@ namespace Artemis.UI.Screens.Sidebar
|
|||||||
|
|
||||||
private void UpdateHeaderDevice()
|
private void UpdateHeaderDevice()
|
||||||
{
|
{
|
||||||
HeaderDevice = _rgbService.Devices.FirstOrDefault(d => d.DeviceType == RGBDeviceType.Keyboard && d.Layout.IsValid);
|
HeaderDevice = _rgbService.Devices.FirstOrDefault(d => d.DeviceType == RGBDeviceType.Keyboard && d.Layout is {IsValid: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArtemisDevice HeaderDevice
|
public ArtemisDevice HeaderDevice
|
||||||
|
|||||||
@ -28,7 +28,6 @@ namespace Artemis.UI.Services
|
|||||||
private const double UpdateCheckInterval = 3600000; // once per hour
|
private const double UpdateCheckInterval = 3600000; // once per hour
|
||||||
private const string ApiUrl = "https://dev.azure.com/artemis-rgb/Artemis/_apis/";
|
private const string ApiUrl = "https://dev.azure.com/artemis-rgb/Artemis/_apis/";
|
||||||
|
|
||||||
private readonly PluginSetting<bool> _autoInstallUpdates;
|
|
||||||
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;
|
||||||
@ -42,7 +41,6 @@ namespace Artemis.UI.Services
|
|||||||
_windowService.MainWindowOpened += WindowServiceOnMainWindowOpened;
|
_windowService.MainWindowOpened += WindowServiceOnMainWindowOpened;
|
||||||
|
|
||||||
_checkForUpdates = settingsService.GetSetting("UI.CheckForUpdates", true);
|
_checkForUpdates = settingsService.GetSetting("UI.CheckForUpdates", true);
|
||||||
_autoInstallUpdates = settingsService.GetSetting("UI.AutoInstallUpdates", false);
|
|
||||||
_checkForUpdates.SettingChanged += CheckForUpdatesOnSettingChanged;
|
_checkForUpdates.SettingChanged += CheckForUpdatesOnSettingChanged;
|
||||||
|
|
||||||
Timer timer = new(UpdateCheckInterval);
|
Timer timer = new(UpdateCheckInterval);
|
||||||
@ -136,18 +134,7 @@ namespace Artemis.UI.Services
|
|||||||
|
|
||||||
if (_windowService.IsMainWindowOpen)
|
if (_windowService.IsMainWindowOpen)
|
||||||
await OfferUpdate(buildInfo);
|
await OfferUpdate(buildInfo);
|
||||||
else if (_autoInstallUpdates.Value)
|
|
||||||
{
|
|
||||||
new ToastContentBuilder()
|
|
||||||
.AddText("Installing new version", AdaptiveTextStyle.Header)
|
|
||||||
.AddText($"Build {buildNumberDisplay} is available, currently on {Constants.BuildInfo.BuildNumberDisplay}.")
|
|
||||||
.AddProgressBar(null, null, true)
|
|
||||||
.Show();
|
|
||||||
|
|
||||||
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.
|
||||||
new ToastContentBuilder()
|
new ToastContentBuilder()
|
||||||
.AddText("New version available", AdaptiveTextStyle.Header)
|
.AddText("New version available", AdaptiveTextStyle.Header)
|
||||||
@ -155,7 +142,6 @@ namespace Artemis.UI.Services
|
|||||||
.AddButton("Update", ToastActivationType.Background, "update")
|
.AddButton("Update", ToastActivationType.Background, "update")
|
||||||
.AddButton("Later", ToastActivationType.Background, "later")
|
.AddButton("Later", ToastActivationType.Background, "later")
|
||||||
.Show(t => t.Activated += TOnActivated);
|
.Show(t => t.Activated += TOnActivated);
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user