diff --git a/src/Artemis.Core/Artemis.Core.csproj.DotSettings b/src/Artemis.Core/Artemis.Core.csproj.DotSettings
index 461cc1c15..261d8170b 100644
--- a/src/Artemis.Core/Artemis.Core.csproj.DotSettings
+++ b/src/Artemis.Core/Artemis.Core.csproj.DotSettings
@@ -57,6 +57,7 @@
True
True
True
+ True
True
True
True
diff --git a/src/Artemis.Core/Events/DataModelPathEventArgs.cs b/src/Artemis.Core/Events/DataModelPathEventArgs.cs
new file mode 100644
index 000000000..6e3da98ed
--- /dev/null
+++ b/src/Artemis.Core/Events/DataModelPathEventArgs.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Artemis.Core
+{
+ ///
+ /// Provides data about data model path related events
+ ///
+ public class DataModelPathEventArgs : EventArgs
+ {
+ internal DataModelPathEventArgs(DataModelPath dataModelPath)
+ {
+ DataModelPath = dataModelPath;
+ }
+
+ ///
+ /// Gets the data model path this event is related to
+ ///
+ public DataModelPath DataModelPath { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/Events/DynamicDataModelChildEventArgs.cs b/src/Artemis.Core/Events/DynamicDataModelChildEventArgs.cs
index 9248a716a..030fd815e 100644
--- a/src/Artemis.Core/Events/DynamicDataModelChildEventArgs.cs
+++ b/src/Artemis.Core/Events/DynamicDataModelChildEventArgs.cs
@@ -1,5 +1,5 @@
using System;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Models/Profile/Conditions/Wrappers/EventPredicateWrapperDataModel.cs b/src/Artemis.Core/Models/Profile/Conditions/Wrappers/EventPredicateWrapperDataModel.cs
index 76e19f3c4..7b30c20f9 100644
--- a/src/Artemis.Core/Models/Profile/Conditions/Wrappers/EventPredicateWrapperDataModel.cs
+++ b/src/Artemis.Core/Models/Profile/Conditions/Wrappers/EventPredicateWrapperDataModel.cs
@@ -1,5 +1,5 @@
using System;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Models/Profile/Conditions/Wrappers/ListPredicateWrapperDataModel.cs b/src/Artemis.Core/Models/Profile/Conditions/Wrappers/ListPredicateWrapperDataModel.cs
index f6eafa524..05b3e598e 100644
--- a/src/Artemis.Core/Models/Profile/Conditions/Wrappers/ListPredicateWrapperDataModel.cs
+++ b/src/Artemis.Core/Models/Profile/Conditions/Wrappers/ListPredicateWrapperDataModel.cs
@@ -1,5 +1,5 @@
using System;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Models/Profile/DataBindings/IDataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/IDataBinding.cs
index c2913c85f..1f54ca146 100644
--- a/src/Artemis.Core/Models/Profile/DataBindings/IDataBinding.cs
+++ b/src/Artemis.Core/Models/Profile/DataBindings/IDataBinding.cs
@@ -1,5 +1,5 @@
using System;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs
index cd56a38b2..352c3c09b 100644
--- a/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs
+++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs
index 4a0431155..edd41bb6a 100644
--- a/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs
+++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelEventArgs.cs
@@ -1,5 +1,5 @@
using System;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs
index c2eb9f1e2..baa7eac6c 100644
--- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs
+++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.Storage.Entities.Profile;
namespace Artemis.Core
@@ -175,6 +175,8 @@ namespace Artemis.Core
internal void Invalidate()
{
+ Target?.RemoveDataModelPath(this);
+
foreach (DataModelPathSegment dataModelPathSegment in _segments)
dataModelPathSegment.Dispose();
_segments.Clear();
@@ -187,11 +189,11 @@ namespace Artemis.Core
internal void Initialize()
{
- Invalidate();
-
if (Target == null)
return;
+ Target.AddDataModelPath(this);
+
DataModelPathSegment startSegment = new(this, "target", "target");
startSegment.Node = _segments.AddFirst(startSegment);
@@ -260,7 +262,7 @@ namespace Artemis.Core
DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
}
-
+
#region IDisposable
///
@@ -330,6 +332,7 @@ namespace Artemis.Core
if (e.Registration.DataModel.Module.Id != Entity.DataModelId)
return;
+ Invalidate();
Target = e.Registration.DataModel;
Initialize();
}
@@ -339,8 +342,8 @@ namespace Artemis.Core
if (e.Registration.DataModel.Module.Id != Entity.DataModelId)
return;
- Target = null;
Invalidate();
+ Target = null;
}
#endregion
diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs
index 7531cb09f..9e5be4a9e 100644
--- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs
+++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Humanizer;
namespace Artemis.Core
@@ -301,7 +301,7 @@ namespace Artemis.Core
private void DynamicChildOnDynamicChildRemoved(object? sender, DynamicDataModelChildEventArgs e)
{
if (e.DynamicChild.BaseValue == _dynamicDataModel)
- DataModelPath.Initialize();
+ DataModelPath.Invalidate();
}
#endregion
diff --git a/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEventArgs.cs b/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEventArgs.cs
index f82169770..b25976a61 100644
--- a/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEventArgs.cs
+++ b/src/Artemis.Core/Models/Profile/DataModel/ValueChangedEvent/DataModelValueChangedEventArgs.cs
@@ -1,4 +1,4 @@
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Models/Profile/ProfileCategory.cs b/src/Artemis.Core/Models/Profile/ProfileCategory.cs
index b5d0b85f2..a15a63e91 100644
--- a/src/Artemis.Core/Models/Profile/ProfileCategory.cs
+++ b/src/Artemis.Core/Models/Profile/ProfileCategory.cs
@@ -5,6 +5,9 @@ using Artemis.Storage.Entities.Profile;
namespace Artemis.Core
{
+ ///
+ /// Represents a category containing
+ ///
public class ProfileCategory : CorePropertyChanged, IStorageModel
{
private readonly List _profileConfigurations = new();
diff --git a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
index 559feecdc..c63bbedef 100644
--- a/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/RenderProfileElement.cs
@@ -59,6 +59,8 @@ namespace Artemis.Core
foreach (BaseLayerEffect baseLayerEffect in LayerEffects)
baseLayerEffect.Dispose();
+ DisplayCondition?.Dispose();
+
base.Dispose(disposing);
}
diff --git a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs
index 01d7ef2dd..f70ef6e9c 100644
--- a/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs
+++ b/src/Artemis.Core/Models/ProfileConfiguration/ProfileConfiguration.cs
@@ -1,13 +1,18 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
using Artemis.Core.Modules;
using Artemis.Storage.Entities.Profile;
namespace Artemis.Core
{
- public class ProfileConfiguration : CorePropertyChanged, IStorageModel
+ ///
+ /// Represents the configuration of a profile, contained in a
+ ///
+ public class ProfileConfiguration : CorePropertyChanged, IStorageModel, IDisposable
{
private ProfileCategory _category;
+ private bool _disposed;
private bool _isMissingModule;
private bool _isSuspended;
@@ -140,11 +145,17 @@ namespace Artemis.Core
///
public void Update()
{
+ if (_disposed)
+ throw new ObjectDisposedException("ProfileConfiguration");
+
ActivationConditionMet = ActivationCondition == null || ActivationCondition.Evaluate();
}
public bool ShouldBeActive(bool includeActivationCondition)
{
+ if (_disposed)
+ throw new ObjectDisposedException("ProfileConfiguration");
+
if (Category.IsSuspended || IsSuspended || IsMissingModule)
return false;
@@ -161,15 +172,32 @@ namespace Artemis.Core
internal void LoadModules(List enabledModules)
{
+ if (_disposed)
+ throw new ObjectDisposedException("ProfileConfiguration");
+
Module = enabledModules.FirstOrDefault(m => m.Id == Entity.ModuleId);
IsMissingModule = Module == null && Entity.ModuleId != null;
}
+ #region IDisposable
+
+ ///
+ public void Dispose()
+ {
+ _disposed = true;
+ ActivationCondition?.Dispose();
+ }
+
+ #endregion
+
#region Implementation of IStorageModel
///
public void Load()
{
+ if (_disposed)
+ throw new ObjectDisposedException("ProfileConfiguration");
+
Name = Entity.Name;
IsSuspended = Entity.IsSuspended;
ActivationBehaviour = (ActivationBehaviour) Entity.ActivationBehaviour;
@@ -185,6 +213,9 @@ namespace Artemis.Core
///
public void Save()
{
+ if (_disposed)
+ throw new ObjectDisposedException("ProfileConfiguration");
+
Entity.Name = Name;
Entity.IsSuspended = IsSuspended;
Entity.ActivationBehaviour = (int) ActivationBehaviour;
@@ -199,9 +230,7 @@ namespace Artemis.Core
Entity.ActivationCondition = ActivationCondition.Entity;
}
else
- {
Entity.ActivationCondition = null;
- }
if (!IsMissingModule)
Entity.ModuleId = Module?.Id;
diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
index 9dec7f4bc..b8034ca26 100644
--- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
+++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs
@@ -549,11 +549,6 @@ namespace Artemis.Core
else
LogicalLayout = DeviceEntity.LogicalLayout;
}
-
- public void ClearLayout()
- {
- // TODO
- }
}
///
diff --git a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
index cd43a0c9a..aa9a5c3cd 100644
--- a/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
+++ b/src/Artemis.Core/Plugins/Modules/ActivationRequirements/ProcessActivationRequirement.cs
@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using Artemis.Core.Services;
+using Ninject;
namespace Artemis.Core.Modules
{
@@ -11,6 +13,8 @@ namespace Artemis.Core.Modules
///
public class ProcessActivationRequirement : IModuleActivationRequirement
{
+ private readonly IProcessMonitorService _processMonitorService;
+
///
/// Creates a new instance of the class
///
@@ -18,6 +22,14 @@ namespace Artemis.Core.Modules
/// The location of where the process must be running from (optional)
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();
+
ProcessName = processName;
Location = location;
}
@@ -38,10 +50,13 @@ namespace Artemis.Core.Modules
if (ProcessName == null && Location == null)
return false;
- IEnumerable processes = ProcessName != null ? Process.GetProcessesByName(ProcessName).Where(p => !p.HasExited) : Process.GetProcesses().Where(p => !p.HasExited);
- return Location != null
- ? processes.Any(p => string.Equals(Path.GetDirectoryName(p.GetProcessFilename()), Location, StringComparison.CurrentCultureIgnoreCase))
- : processes.Any();
+ IEnumerable processes = _processMonitorService.GetRunningProcesses();
+ if (ProcessName != null)
+ processes = processes.Where(p => string.Equals(p.ProcessName, ProcessName, StringComparison.InvariantCultureIgnoreCase));
+ if (Location != null)
+ processes = processes.Where(p => string.Equals(Path.GetDirectoryName(p.GetProcessFilename()), Location, StringComparison.InvariantCultureIgnoreCase));
+
+ return processes.Any();
}
///
diff --git a/src/Artemis.Core/Plugins/Modules/Attributes/DataModelIgnoreAttribute.cs b/src/Artemis.Core/Plugins/Modules/Attributes/DataModelIgnoreAttribute.cs
index a9339b2ee..6f3d06387 100644
--- a/src/Artemis.Core/Plugins/Modules/Attributes/DataModelIgnoreAttribute.cs
+++ b/src/Artemis.Core/Plugins/Modules/Attributes/DataModelIgnoreAttribute.cs
@@ -1,6 +1,6 @@
using System;
-namespace Artemis.Core.DataModelExpansions
+namespace Artemis.Core.Modules
{
///
/// Represents an attribute that marks a data model property to be ignored by the UI
diff --git a/src/Artemis.Core/Plugins/Modules/Attributes/DataModelProperty.cs b/src/Artemis.Core/Plugins/Modules/Attributes/DataModelProperty.cs
index 3f6ee745a..11fe2993f 100644
--- a/src/Artemis.Core/Plugins/Modules/Attributes/DataModelProperty.cs
+++ b/src/Artemis.Core/Plugins/Modules/Attributes/DataModelProperty.cs
@@ -1,6 +1,6 @@
using System;
-namespace Artemis.Core.DataModelExpansions
+namespace Artemis.Core.Modules
{
///
/// Represents an attribute that describes a data model property
diff --git a/src/Artemis.Core/Plugins/Modules/DataModel.cs b/src/Artemis.Core/Plugins/Modules/DataModel.cs
index 1321b705a..b4c89b08b 100644
--- a/src/Artemis.Core/Plugins/Modules/DataModel.cs
+++ b/src/Artemis.Core/Plugins/Modules/DataModel.cs
@@ -1,21 +1,21 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
-using Artemis.Core.Modules;
using Humanizer;
using Newtonsoft.Json;
-using Module = Artemis.Core.Modules.Module;
-namespace Artemis.Core.DataModelExpansions
+namespace Artemis.Core.Modules
{
///
/// Represents a data model that contains information on a game/application etc.
///
public abstract class DataModel
{
+ private readonly HashSet _activePathsHashSet = new();
+ private readonly List _activePaths = new();
private readonly Dictionary _dynamicChildren = new();
///
@@ -54,42 +54,18 @@ namespace Artemis.Core.DataModelExpansions
[DataModelIgnore]
public ReadOnlyDictionary DynamicChildren => new(_dynamicChildren);
+ ///
+ /// Gets a read-only list of s targeting this data model
+ ///
+ public ReadOnlyCollection ActivePaths => _activePaths.AsReadOnly();
+
///
/// Returns a read-only collection of all properties in this datamodel that are to be ignored
///
///
public ReadOnlyCollection GetHiddenProperties()
{
- if (Module is Module module)
- return module.HiddenProperties;
-
- return new List().AsReadOnly();
- }
-
- ///
- /// Occurs when a dynamic child has been added to this data model
- ///
- public event EventHandler? DynamicChildAdded;
-
- ///
- /// Occurs when a dynamic child has been removed from this data model
- ///
- public event EventHandler? DynamicChildRemoved;
-
- ///
- /// Invokes the event
- ///
- protected virtual void OnDynamicDataModelAdded(DynamicDataModelChildEventArgs e)
- {
- DynamicChildAdded?.Invoke(this, e);
- }
-
- ///
- /// Invokes the event
- ///
- protected virtual void OnDynamicDataModelRemoved(DynamicDataModelChildEventArgs e)
- {
- DynamicChildRemoved?.Invoke(this, e);
+ return Module.HiddenProperties;
}
#region Dynamic children
@@ -277,5 +253,108 @@ namespace Artemis.Core.DataModelExpansions
}
#endregion
+
+ #region Paths
+
+ ///
+ /// Determines whether the provided dot-separated path is in use
+ ///
+ /// The path to check per example: MyDataModelChild.MyDataModelProperty
+ ///
+ /// If any child of the given path will return true as well; if
+ /// only an exact path match returns .
+ ///
+ 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
+
+ ///
+ /// Occurs when a dynamic child has been added to this data model
+ ///
+ public event EventHandler? DynamicChildAdded;
+
+ ///
+ /// Occurs when a dynamic child has been removed from this data model
+ ///
+ public event EventHandler? DynamicChildRemoved;
+
+ ///
+ /// Occurs when a dynamic child has been added to this data model
+ ///
+ public event EventHandler? ActivePathAdded;
+
+ ///
+ /// Occurs when a dynamic child has been removed from this data model
+ ///
+ public event EventHandler? ActivePathRemoved;
+
+ ///
+ /// Invokes the event
+ ///
+ protected virtual void OnDynamicDataModelAdded(DynamicDataModelChildEventArgs e)
+ {
+ DynamicChildAdded?.Invoke(this, e);
+ }
+
+ ///
+ /// Invokes the event
+ ///
+ protected virtual void OnDynamicDataModelRemoved(DynamicDataModelChildEventArgs e)
+ {
+ DynamicChildRemoved?.Invoke(this, e);
+ }
+
+ ///
+ /// Invokes the event
+ ///
+ protected virtual void OnActivePathAdded(DataModelPathEventArgs e)
+ {
+ ActivePathAdded?.Invoke(this, e);
+ }
+
+ ///
+ /// Invokes the event
+ ///
+ protected virtual void OnActivePathRemoved(DataModelPathEventArgs e)
+ {
+ ActivePathRemoved?.Invoke(this, e);
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.Core/Plugins/Modules/DynamicChild.cs b/src/Artemis.Core/Plugins/Modules/DynamicChild.cs
index 5e5732b55..203562865 100644
--- a/src/Artemis.Core/Plugins/Modules/DynamicChild.cs
+++ b/src/Artemis.Core/Plugins/Modules/DynamicChild.cs
@@ -1,6 +1,6 @@
using System;
-namespace Artemis.Core.DataModelExpansions
+namespace Artemis.Core.Modules
{
///
/// Represents a dynamic child value with its property attribute
diff --git a/src/Artemis.Core/Plugins/Modules/Module.cs b/src/Artemis.Core/Plugins/Modules/Module.cs
index edf3cb340..aa2d84691 100644
--- a/src/Artemis.Core/Plugins/Modules/Module.cs
+++ b/src/Artemis.Core/Plugins/Modules/Module.cs
@@ -5,7 +5,7 @@ using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
-using Artemis.Core.DataModelExpansions;
+using System.Text;
namespace Artemis.Core.Modules
{
@@ -25,7 +25,8 @@ namespace Artemis.Core.Modules
}
///
- /// 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.
+ /// HideProperty(dm => dm.TimeDataModel.CurrentTimeUTC)
///
/// A lambda expression pointing to the property to ignore
public void HideProperty(Expression> propertyLambda)
@@ -36,8 +37,8 @@ namespace Artemis.Core.Modules
}
///
- /// Stop hiding the provided property using a lambda expression, e.g. ShowProperty(dm =>
- /// dm.TimeDataModel.CurrentTimeUTC)
+ /// Stop hiding the provided property using a lambda expression, e.g.
+ /// ShowProperty(dm => dm.TimeDataModel.CurrentTimeUTC)
///
/// A lambda expression pointing to the property to stop ignoring
public void ShowProperty(Expression> propertyLambda)
@@ -46,6 +47,36 @@ namespace Artemis.Core.Modules
HiddenPropertiesList.RemoveAll(p => p.Equals(propertyInfo));
}
+ ///
+ /// Determines whether the provided dot-separated path is actively being used by Artemis
+ /// Note: is slightly faster but string-based.
+ ///
+ ///
+ /// The path to check per example: IsPropertyInUse(dm => dm.TimeDataModel.CurrentTimeUTC)
+ ///
+ ///
+ /// If any child of the given path will return true as well; if
+ /// only an exact path match returns .
+ ///
+ public bool IsPropertyInUse(Expression> propertyLambda, bool includeChildren)
+ {
+ string path = GetMemberPath((MemberExpression) propertyLambda.Body);
+ return IsPropertyInUse(path, includeChildren);
+ }
+
+ ///
+ /// Determines whether the provided dot-separated path is actively being used by Artemis
+ ///
+ /// The path to check per example: MyDataModelChild.MyDataModelProperty
+ ///
+ /// If any child of the given path will return true as well; if
+ /// only an exact path match returns .
+ ///
+ public bool IsPropertyInUse(string path, bool includeChildren)
+ {
+ return DataModel.IsPropertyInUse(path, includeChildren);
+ }
+
internal override void InternalEnable()
{
DataModel = Activator.CreateInstance();
@@ -59,6 +90,20 @@ namespace Artemis.Core.Modules
Deactivate(true);
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();
+ }
}
///
@@ -78,7 +123,7 @@ namespace Artemis.Core.Modules
/// Gets a read only collection of default profile paths
///
public IReadOnlyCollection<(DefaultCategoryName, string)> DefaultProfilePaths => _defaultProfilePaths.AsReadOnly();
-
+
///
/// A list of activation requirements
///
diff --git a/src/Artemis.Core/Plugins/TimedUpdateRegistration.cs b/src/Artemis.Core/Plugins/TimedUpdateRegistration.cs
index 39d5ad8cb..a2a189745 100644
--- a/src/Artemis.Core/Plugins/TimedUpdateRegistration.cs
+++ b/src/Artemis.Core/Plugins/TimedUpdateRegistration.cs
@@ -22,6 +22,8 @@ namespace Artemis.Core
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Action action, string? name)
{
+ if (CoreService.Kernel == null)
+ throw new ArtemisCoreException("Cannot create a TimedUpdateRegistration before initializing the Core");
_logger = CoreService.Kernel.Get();
Feature = feature;
@@ -37,6 +39,8 @@ namespace Artemis.Core
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Func asyncAction, string? name)
{
+ if (CoreService.Kernel == null)
+ throw new ArtemisCoreException("Cannot create a TimedUpdateRegistration before initializing the Core");
_logger = CoreService.Kernel.Get();
Feature = feature;
diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs
index b07ba5861..f2a279a6f 100644
--- a/src/Artemis.Core/Services/CoreService.cs
+++ b/src/Artemis.Core/Services/CoreService.cs
@@ -4,7 +4,6 @@ using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
-using Artemis.Core.DataModelExpansions;
using Artemis.Core.Ninject;
using Artemis.Storage;
using HidSharp;
@@ -22,7 +21,7 @@ namespace Artemis.Core.Services
///
internal class CoreService : ICoreService
{
- internal static IKernel Kernel = null!;
+ internal static IKernel? Kernel;
private readonly Stopwatch _frameStopWatch;
private readonly ILogger _logger;
@@ -201,7 +200,7 @@ namespace Artemis.Core.Services
Version? hidSharpVersion = Assembly.GetAssembly(typeof(HidDevice))!.GetName().Version;
_logger.Debug("Forcing plugins to use HidSharp {hidSharpVersion}", hidSharpVersion);
- DeserializationLogger.Initialize(Kernel);
+ DeserializationLogger.Initialize(Kernel!);
// Initialize the services
_pluginManagementService.CopyBuiltInPlugins();
diff --git a/src/Artemis.Core/Services/Registration/DataModelService.cs b/src/Artemis.Core/Services/Registration/DataModelService.cs
index 90e1c4739..450d2f239 100644
--- a/src/Artemis.Core/Services/Registration/DataModelService.cs
+++ b/src/Artemis.Core/Services/Registration/DataModelService.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
namespace Artemis.Core.Services
diff --git a/src/Artemis.Core/Services/Registration/Interfaces/IDataModelService.cs b/src/Artemis.Core/Services/Registration/Interfaces/IDataModelService.cs
index 072c68601..9d5b390fc 100644
--- a/src/Artemis.Core/Services/Registration/Interfaces/IDataModelService.cs
+++ b/src/Artemis.Core/Services/Registration/Interfaces/IDataModelService.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core.Services
{
diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs
index e65b74b4b..22d7b1c66 100644
--- a/src/Artemis.Core/Services/RgbService.cs
+++ b/src/Artemis.Core/Services/RgbService.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
+using System.Threading;
using Artemis.Core.DeviceProviders;
using Artemis.Core.Services.Models;
using Artemis.Core.SkiaSharp;
@@ -345,6 +346,13 @@ namespace Artemis.Core.Services
return layout;
}
+ if (device.DisableDefaultLayout)
+ {
+ layout = null;
+ ApplyDeviceLayout(device, layout);
+ return null;
+ }
+
// Look for a layout provided by the plugin
layout = device.DeviceProvider.LoadLayout(device);
if (layout.IsValid)
@@ -354,8 +362,7 @@ namespace Artemis.Core.Services
}
// Finally fall back to a default layout
- if (!device.DisableDefaultLayout)
- layout = ArtemisLayout.GetDefaultLayout(device);
+ layout = ArtemisLayout.GetDefaultLayout(device);
ApplyDeviceLayout(device, layout);
return layout;
}
@@ -365,7 +372,7 @@ namespace Artemis.Core.Services
if (layout == null)
{
if (device.Layout != null)
- device.ClearLayout();
+ ReloadDevice(device);
return;
}
@@ -377,6 +384,16 @@ namespace Artemis.Core.Services
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)
{
return _devices.FirstOrDefault(d => d.RgbDevice == rgbDevice);
diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs
index 41efce23d..b3fb0c267 100644
--- a/src/Artemis.Core/Services/Storage/ProfileService.cs
+++ b/src/Artemis.Core/Services/Storage/ProfileService.cs
@@ -357,6 +357,8 @@ namespace Artemis.Core.Services
ProfileEntity profileEntity = _profileRepository.Get(profileConfiguration.Entity.ProfileId);
if (profileEntity != null)
_profileRepository.Remove(profileEntity);
+
+ profileConfiguration.Dispose();
}
public void SaveProfileCategory(ProfileCategory profileCategory)
diff --git a/src/Artemis.Core/Services/WebServer/EndPoints/DataModelJsonPluginEndPoint.cs b/src/Artemis.Core/Services/WebServer/EndPoints/DataModelJsonPluginEndPoint.cs
index d0e5e206b..70a019331 100644
--- a/src/Artemis.Core/Services/WebServer/EndPoints/DataModelJsonPluginEndPoint.cs
+++ b/src/Artemis.Core/Services/WebServer/EndPoints/DataModelJsonPluginEndPoint.cs
@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Threading.Tasks;
-using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using EmbedIO;
using Newtonsoft.Json;
diff --git a/src/Artemis.Core/Services/WebServer/Interfaces/IWebServerService.cs b/src/Artemis.Core/Services/WebServer/Interfaces/IWebServerService.cs
index 22051d7fd..7c8e2124f 100644
--- a/src/Artemis.Core/Services/WebServer/Interfaces/IWebServerService.cs
+++ b/src/Artemis.Core/Services/WebServer/Interfaces/IWebServerService.cs
@@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
-using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using EmbedIO;
using EmbedIO.WebApi;
diff --git a/src/Artemis.Core/Services/WebServer/WebServerService.cs b/src/Artemis.Core/Services/WebServer/WebServerService.cs
index 4c9272d91..0d7654812 100644
--- a/src/Artemis.Core/Services/WebServer/WebServerService.cs
+++ b/src/Artemis.Core/Services/WebServer/WebServerService.cs
@@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using EmbedIO;
using EmbedIO.WebApi;
diff --git a/src/Artemis.Core/Stores/DataModelStore.cs b/src/Artemis.Core/Stores/DataModelStore.cs
index 336dac6f5..160aed9c2 100644
--- a/src/Artemis.Core/Stores/DataModelStore.cs
+++ b/src/Artemis.Core/Stores/DataModelStore.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Stores/Registrations/DataModelRegistration.cs b/src/Artemis.Core/Stores/Registrations/DataModelRegistration.cs
index 09c162758..c1eb7f789 100644
--- a/src/Artemis.Core/Stores/Registrations/DataModelRegistration.cs
+++ b/src/Artemis.Core/Stores/Registrations/DataModelRegistration.cs
@@ -1,5 +1,5 @@
using System;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.Core/Utilities/ExpressionUtilities.cs b/src/Artemis.Core/Utilities/ExpressionUtilities.cs
index 4db041961..e460feba1 100644
--- a/src/Artemis.Core/Utilities/ExpressionUtilities.cs
+++ b/src/Artemis.Core/Utilities/ExpressionUtilities.cs
@@ -1,5 +1,5 @@
using System.Linq.Expressions;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
namespace Artemis.Core
{
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs
index 16edde678..abbc4171d 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs
@@ -1,5 +1,5 @@
using System.Diagnostics.CodeAnalysis;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Stylet;
namespace Artemis.UI.Shared
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
index 1c147ac43..1c9574dfb 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
@@ -5,7 +5,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Stylet;
namespace Artemis.UI.Shared
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs
index fa4ad2f99..ad6697b92 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs
@@ -272,6 +272,7 @@ namespace Artemis.UI.Shared.Input
_updateTimer.Dispose();
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
+ DataModelViewModel?.Dispose();
DataModelPath?.Dispose();
}
}
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs
index d909eb9ba..2ef06ec9a 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelStaticViewModel.cs
@@ -4,7 +4,7 @@ using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Artemis.Core;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared.Services;
using MaterialDesignColors.ColorManipulation;
using Stylet;
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelEventViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelEventViewModel.cs
index 5fab8425c..55ccdf424 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelEventViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelEventViewModel.cs
@@ -1,7 +1,7 @@
using System;
using System.Linq;
using Artemis.Core;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared.Services;
namespace Artemis.UI.Shared
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
index c36d7129e..09187f910 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
@@ -2,7 +2,7 @@
using System.Collections;
using System.Windows.Documents;
using Artemis.Core;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared.Services;
using Stylet;
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs
index 99092a24a..423af79e9 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertiesViewModel.cs
@@ -1,6 +1,6 @@
using System;
using Artemis.Core;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared.Services;
namespace Artemis.UI.Shared
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertyViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertyViewModel.cs
index 3d3b20102..5f4b35891 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertyViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertyViewModel.cs
@@ -1,6 +1,6 @@
using System;
using Artemis.Core;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared.Services;
namespace Artemis.UI.Shared
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
index 78490468a..47f3341d2 100644
--- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
@@ -3,8 +3,9 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
+using System.Text;
using Artemis.Core;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared.Services;
using Stylet;
@@ -13,7 +14,7 @@ namespace Artemis.UI.Shared
///
/// Represents a base class for a view model that visualizes a part of the data model
///
- public abstract class DataModelVisualizationViewModel : PropertyChangedBase
+ public abstract class DataModelVisualizationViewModel : PropertyChangedBase, IDisposable
{
private const int MaxDepth = 4;
private BindableCollection _children;
@@ -22,6 +23,7 @@ namespace Artemis.UI.Shared
private bool _isVisualizationExpanded;
private DataModelVisualizationViewModel? _parent;
private DataModelPropertyAttribute? _propertyDescription;
+ private bool _populatedStaticChildren;
internal DataModelVisualizationViewModel(DataModel? dataModel, DataModelVisualizationViewModel? parent, DataModelPath? dataModelPath)
{
@@ -206,21 +208,26 @@ namespace Artemis.UI.Shared
if (modelType == null)
throw new ArtemisSharedUIException("Failed to populate data model visualization properties, couldn't get a property type");
- // Add missing static children
- foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(t => t.MetadataToken))
+ // Add missing static children only once, they're static after all
+ if (!_populatedStaticChildren)
{
- string childPath = AppendToPath(propertyInfo.Name);
- if (Children.Any(c => c.Path != null && c.Path.Equals(childPath)))
- continue;
- if (propertyInfo.GetCustomAttribute() != null)
- continue;
- MethodInfo? getMethod = propertyInfo.GetGetMethod();
- if (getMethod == null || getMethod.GetParameters().Any())
- continue;
+ foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(t => t.MetadataToken))
+ {
+ string childPath = AppendToPath(propertyInfo.Name);
+ if (Children.Any(c => c.Path != null && c.Path.Equals(childPath)))
+ continue;
+ if (propertyInfo.GetCustomAttribute() != null)
+ continue;
+ MethodInfo? getMethod = propertyInfo.GetGetMethod();
+ if (getMethod == null || getMethod.GetParameters().Any())
+ continue;
- DataModelVisualizationViewModel? child = CreateChild(dataModelUIService, childPath, GetChildDepth());
- if (child != null)
- Children.Add(child);
+ DataModelVisualizationViewModel? child = CreateChild(dataModelUIService, childPath, GetChildDepth());
+ if (child != null)
+ Children.Add(child);
+ }
+
+ _populatedStaticChildren = true;
}
// Remove static children that should be hidden
@@ -302,7 +309,14 @@ namespace Artemis.UI.Shared
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()
@@ -327,5 +341,33 @@ namespace Artemis.UI.Shared
}
#endregion
+
+ #region IDisposable
+
+ ///
+ /// Releases the unmanaged resources used by the object and optionally releases the managed resources.
+ ///
+ ///
+ /// to release both managed and unmanaged resources;
+ /// to release only unmanaged resources.
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ DataModelPath?.Dispose();
+ foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
+ dataModelVisualizationViewModel.Dispose(true);
+ }
+ }
+
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Ninject/Factories/ISharedVMFactory.cs b/src/Artemis.UI.Shared/Ninject/Factories/ISharedVMFactory.cs
index ee1c48316..21cce1e60 100644
--- a/src/Artemis.UI.Shared/Ninject/Factories/ISharedVMFactory.cs
+++ b/src/Artemis.UI.Shared/Ninject/Factories/ISharedVMFactory.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using Artemis.UI.Shared.Input;
diff --git a/src/Artemis.UI.Shared/Services/DataModelUIService.cs b/src/Artemis.UI.Shared/Services/DataModelUIService.cs
index 6066de626..dc8e5ca7e 100644
--- a/src/Artemis.UI.Shared/Services/DataModelUIService.cs
+++ b/src/Artemis.UI.Shared/Services/DataModelUIService.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using Artemis.Core;
-using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Artemis.UI.Shared.DefaultTypes.DataModel.Display;
diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs
index 5da6a381b..2c3f6efdb 100644
--- a/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs
+++ b/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using Artemis.Core;
-using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using Artemis.UI.Shared.Input;
diff --git a/src/Artemis.UI/ApplicationStateManager.cs b/src/Artemis.UI/ApplicationStateManager.cs
index 2a08b4a3a..45dc2098c 100644
--- a/src/Artemis.UI/ApplicationStateManager.cs
+++ b/src/Artemis.UI/ApplicationStateManager.cs
@@ -7,10 +7,8 @@ using System.Net.Http;
using System.Reflection;
using System.Security.Principal;
using System.Threading;
-using System.Threading.Tasks;
using System.Windows;
using Artemis.Core;
-using Artemis.UI.Screens;
using Artemis.UI.Utilities;
using Ninject;
using Ookii.Dialogs.Wpf;
@@ -44,30 +42,82 @@ namespace Artemis.UI
if (createdNew)
return false;
- try
- {
- // 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;
+ return RemoteFocus();
}
- private async Task RemoteFocus()
+ public void DisplayException(Exception e)
+ {
+ using TaskDialog dialog = new();
+ AssemblyInformationalVersionAttribute versionAttribute = typeof(ApplicationStateManager).Assembly.GetCustomAttribute();
+ 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 wiki or hit us up on Discord.";
+ 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.
// Instead use the method external applications should use as well.
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();
- 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 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)
@@ -134,39 +184,6 @@ namespace Artemis.UI
Execute.OnUIThread(() => Application.Current.Shutdown());
}
- public void DisplayException(Exception e)
- {
- using TaskDialog dialog = new();
- AssemblyInformationalVersionAttribute versionAttribute = typeof(ApplicationStateManager).Assembly.GetCustomAttribute();
- 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 wiki or hit us up on Discord.";
- 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)
{
ProcessStartInfo processInfo = new()
diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputViewModel.cs b/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputViewModel.cs
index d4f966351..8b65a2075 100644
--- a/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputViewModel.cs
@@ -1,4 +1,4 @@
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared;
namespace Artemis.UI.DefaultTypes.DataModel.Input
diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/DoubleDataModelInputViewModel.cs b/src/Artemis.UI/DefaultTypes/DataModel/Input/DoubleDataModelInputViewModel.cs
index 4fe8e02ef..a0e946d89 100644
--- a/src/Artemis.UI/DefaultTypes/DataModel/Input/DoubleDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/DoubleDataModelInputViewModel.cs
@@ -1,7 +1,7 @@
using System.Globalization;
using System.Text.RegularExpressions;
using System.Windows.Input;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared;
namespace Artemis.UI.DefaultTypes.DataModel.Input
diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputViewModel.cs b/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputViewModel.cs
index ec374e67a..e995a49c3 100644
--- a/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputViewModel.cs
@@ -1,5 +1,5 @@
using System;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared;
using Stylet;
diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/IntDataModelInputViewModel.cs b/src/Artemis.UI/DefaultTypes/DataModel/Input/IntDataModelInputViewModel.cs
index 4a9ba6487..13faa7e2f 100644
--- a/src/Artemis.UI/DefaultTypes/DataModel/Input/IntDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/IntDataModelInputViewModel.cs
@@ -1,6 +1,6 @@
using System.Text.RegularExpressions;
using System.Windows.Input;
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared;
namespace Artemis.UI.DefaultTypes.DataModel.Input
diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/SKColorDataModelInputViewModel.cs b/src/Artemis.UI/DefaultTypes/DataModel/Input/SKColorDataModelInputViewModel.cs
index 02c1beb5f..93aafd576 100644
--- a/src/Artemis.UI/DefaultTypes/DataModel/Input/SKColorDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/SKColorDataModelInputViewModel.cs
@@ -1,4 +1,4 @@
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared;
using SkiaSharp;
diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/StringDataModelInputViewModel.cs b/src/Artemis.UI/DefaultTypes/DataModel/Input/StringDataModelInputViewModel.cs
index 284a3fd08..450664b01 100644
--- a/src/Artemis.UI/DefaultTypes/DataModel/Input/StringDataModelInputViewModel.cs
+++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/StringDataModelInputViewModel.cs
@@ -1,4 +1,4 @@
-using Artemis.Core.DataModelExpansions;
+using Artemis.Core.Modules;
using Artemis.UI.Shared;
namespace Artemis.UI.DefaultTypes.DataModel.Input
diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
index f566bf8d2..5aa6a6515 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
@@ -9,6 +9,7 @@ using System.Windows.Media;
using Artemis.Core;
using Artemis.Core.LayerEffects;
using Artemis.Core.Services;
+using Artemis.UI.Extensions;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings;
using Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects;
@@ -220,7 +221,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
private void SelectedProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
{
- PopulateProperties(e.RenderProfileElement);
+ Execute.PostToUIThread(() => PopulateProperties(e.RenderProfileElement));
}
private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e)
@@ -347,7 +348,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
.ToList();
// Order the effects
List effectProperties = Items
- .Where(l => l.TreeGroupViewModel.GroupType == LayerEffectRoot)
+ .Where(l => l.TreeGroupViewModel.GroupType == LayerEffectRoot && l.LayerPropertyGroup.LayerEffect != null)
.OrderBy(l => l.LayerPropertyGroup.LayerEffect.Order)
.ToList();
@@ -355,14 +356,16 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
for (int index = 0; index < nonEffectProperties.Count; index++)
{
LayerPropertyGroupViewModel layerPropertyGroupViewModel = nonEffectProperties[index];
- ((BindableCollection) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index);
+ if (Items.IndexOf(layerPropertyGroupViewModel) != index)
+ ((BindableCollection) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index);
}
// Put the effect properties after, sorted by their order
for (int index = 0; index < effectProperties.Count; index++)
{
LayerPropertyGroupViewModel layerPropertyGroupViewModel = effectProperties[index];
- ((BindableCollection) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count);
+ if (Items.IndexOf(layerPropertyGroupViewModel) != index + nonEffectProperties.Count)
+ ((BindableCollection) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count);
}
}
@@ -527,7 +530,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
Repeating = false;
}
}
-
+
private TimeSpan GetCurrentSegmentStart()
{
TimeSpan current = ProfileEditorService.CurrentTime;
@@ -637,7 +640,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
public void TimelineJump(object sender, MouseButtonEventArgs e)
{
// 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);
TimeSpan newTime = TimeSpan.FromSeconds(x / ProfileEditorService.PixelsPerSecond);
diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeView.xaml b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeView.xaml
index a949eee63..c3388512a 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeView.xaml
+++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeView.xaml
@@ -15,6 +15,15 @@
d:DataContext="{d:DesignInstance {x:Type profileTree1:ProfileTreeViewModel}}">
+
+
+
+
+
+
+
@@ -33,7 +42,10 @@
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
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}">
diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs
index ea167ba29..9156b86f1 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs
@@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Windows;
+using System.Windows.Input;
using Artemis.Core;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem;
@@ -15,6 +16,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
{
private readonly IProfileEditorService _profileEditorService;
private readonly IProfileTreeVmFactory _profileTreeVmFactory;
+ private bool _draggingTreeView;
private TreeItemViewModel _selectedTreeItem;
private bool _updatingTree;
@@ -31,18 +33,24 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
get => _selectedTreeItem;
set
{
- if (_updatingTree) return;
- if (!SetAndNotify(ref _selectedTreeItem, value)) return;
-
- if (value != null && value.ProfileElement is RenderProfileElement renderElement)
- _profileEditorService.ChangeSelectedProfileElement(renderElement);
- else
- _profileEditorService.ChangeSelectedProfileElement(null);
+ if (!_updatingTree && SetAndNotify(ref _selectedTreeItem, value) && !_draggingTreeView)
+ ApplySelectedTreeItem();
}
}
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()
{
Subscribe();
@@ -55,6 +63,14 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
base.OnClose();
}
+ private void ApplySelectedTreeItem()
+ {
+ if (_selectedTreeItem != null && _selectedTreeItem.ProfileElement is RenderProfileElement renderElement)
+ _profileEditorService.ChangeSelectedProfileElement(renderElement);
+ else
+ _profileEditorService.ChangeSelectedProfileElement(null);
+ }
+
private void CreateRootFolderViewModel()
{
_updatingTree = true;
@@ -64,7 +80,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
ActivateItem(null);
return;
}
-
+
ActiveItem = _profileTreeVmFactory.FolderViewModel(folder);
_updatingTree = false;
}
diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs
index 2ae8702b1..e4309201c 100644
--- a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs
+++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs
@@ -184,6 +184,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
else
newSelection = ProfileElement.Parent;
}
+ _profileEditorService.ChangeSelectedProfileElement(newSelection as RenderProfileElement);
// Farewell, cruel world
TreeItemViewModel parent = (TreeItemViewModel) Parent;
@@ -191,7 +192,6 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem
parent.RemoveExistingElement(this);
_profileEditorService.SaveSelectedProfileConfiguration();
- _profileEditorService.ChangeSelectedProfileElement(newSelection as RenderProfileElement);
}
public void DuplicateElement()
diff --git a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
index 32dbb01b5..7825cc03b 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
@@ -87,7 +87,7 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
protected override void OnClose()
{
_updateTimer.Dispose();
- base.OnClose();
+ base.OnClose();
}
#endregion
@@ -109,6 +109,9 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
{
_updateTimer.Stop();
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
+ MainDataModel?.Dispose();
+ MainDataModel = null;
+
_pluginManagementService.PluginFeatureEnabled -= OnPluginFeatureToggled;
_pluginManagementService.PluginFeatureDisabled -= OnPluginFeatureToggled;
diff --git a/src/Artemis.UI/Screens/Settings/Device/DeviceDialogViewModel.cs b/src/Artemis.UI/Screens/Settings/Device/DeviceDialogViewModel.cs
index 0cd156be7..97f47d8c7 100644
--- a/src/Artemis.UI/Screens/Settings/Device/DeviceDialogViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Device/DeviceDialogViewModel.cs
@@ -25,9 +25,11 @@ namespace Artemis.UI.Screens.Settings.Device
private readonly ICoreService _coreService;
private readonly IDeviceService _deviceService;
private readonly IDialogService _dialogService;
+ private readonly IDeviceDebugVmFactory _factory;
private readonly IRgbService _rgbService;
private SnackbarMessageQueue _deviceMessageQueue;
private BindableCollection _selectedLeds;
+ private ArtemisDevice _device;
public DeviceDialogViewModel(ArtemisDevice device,
ICoreService coreService,
@@ -40,22 +42,46 @@ namespace Artemis.UI.Screens.Settings.Device
_deviceService = deviceService;
_rgbService = rgbService;
_dialogService = dialogService;
+ _factory = factory;
- Device = device;
PanZoomViewModel = new PanZoomViewModel();
SelectedLeds = new BindableCollection();
- 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.First();
- DisplayName = $"{device.RgbDevice.DeviceInfo.Model} | Artemis";
+ Initialize(device);
+ }
+
+ private void Initialize(ArtemisDevice device)
+ {
+ if (SelectedLeds.Any())
+ SelectedLeds.Clear();
+
+ 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 SnackbarMessageQueue DeviceMessageQueue
@@ -84,14 +110,21 @@ namespace Artemis.UI.Screens.Settings.Device
protected override void OnInitialActivate()
{
_coreService.FrameRendering += CoreServiceOnFrameRendering;
+ _rgbService.DeviceAdded += RgbServiceOnDeviceAdded;
DeviceMessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(5));
- Device.DeviceUpdated += DeviceOnDeviceUpdated;
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()
{
_coreService.FrameRendering -= CoreServiceOnFrameRendering;
+ _rgbService.DeviceAdded -= RgbServiceOnDeviceAdded;
Device.DeviceUpdated -= DeviceOnDeviceUpdated;
base.OnClose();
}
diff --git a/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabView.xaml b/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabView.xaml
index 344e87fee..f1ff314ac 100644
--- a/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabView.xaml
@@ -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.
-
+
- Use default layout if needed
+ Don't load default layout
+ ToolTip="With this enabled Artemis will not load a layout for this device unless you specifically provide one." />
diff --git a/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs b/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs
index af4f44aa4..244b7e448 100644
--- a/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Device/Tabs/DevicePropertiesTabViewModel.cs
@@ -101,7 +101,7 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
get => _displayOnDevices;
set => SetAndNotify(ref _displayOnDevices, value);
}
-
+
// This solution won't scale well but I don't expect there to be many more categories.
// If for some reason there will be, dynamically creating a view model per category may be more appropriate
public bool HasDeskCategory
@@ -134,16 +134,6 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
set => SetCategory(DeviceCategory.Peripherals, value);
}
- public bool UseDefaultLayout
- {
- get => !Device.DisableDefaultLayout;
- set
- {
- Device.DisableDefaultLayout = !value;
- NotifyOfPropertyChange(nameof(UseDefaultLayout));
- }
- }
-
public void ApplyScaling()
{
Device.RedScale = RedScale / 100f;
@@ -266,7 +256,9 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
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)
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsTabViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsTabViewModel.cs
index ee9c2f793..e775065a3 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsTabViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Tabs/Devices/DeviceSettingsTabViewModel.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services;
@@ -10,9 +11,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
{
public class DeviceSettingsTabViewModel : Conductor.Collection.AllActive
{
- private readonly ISettingsVmFactory _settingsVmFactory;
- private readonly IRgbService _rgbService;
private readonly IDialogService _dialogService;
+ private readonly IRgbService _rgbService;
+ private readonly ISettingsVmFactory _settingsVmFactory;
private bool _confirmedDisable;
public DeviceSettingsTabViewModel(IRgbService rgbService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
@@ -24,28 +25,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
_settingsVmFactory = settingsVmFactory;
}
- #region Overrides of AllActive
-
- ///
- 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 instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
- foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances)
- Items.Add(deviceSettingsViewModel);
- });
- base.OnActivate();
- }
-
- #endregion
-
public async Task ShowDeviceDisableDialog()
{
if (_confirmedDisable)
@@ -61,5 +40,49 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
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
+
+ ///
+ 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 instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
+ foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances)
+ Items.Add(deviceSettingsViewModel);
+ });
+ base.OnActivate();
+ }
+
+ ///
+ protected override void OnClose()
+ {
+ _rgbService.DeviceAdded -= RgbServiceOnDeviceAdded;
+ _rgbService.DeviceRemoved -= RgbServiceOnDeviceRemoved;
+ base.OnClose();
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml
index 7153e747c..504f87002 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabView.xaml
@@ -218,27 +218,6 @@
-
-
-
-
-
-
-
-
-
-
- Automatically install updates
-
- If enabled updates are installed automatically without asking first.
-
-
-
-
-
-
-
-
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
index 2f8978ef4..895d903a0 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
@@ -158,20 +158,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
_settingsService.GetSetting("UI.CheckForUpdates", true).Value = value;
_settingsService.GetSetting("UI.CheckForUpdates", true).Save();
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));
}
}
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml b/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml
index 85ede98d4..209f1b250 100644
--- a/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarView.xaml
@@ -91,14 +91,10 @@
-
-
-
-
-
+
+
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
index 7ed65869e..a80f0f929 100644
--- a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
@@ -69,7 +69,7 @@ namespace Artemis.UI.Screens.Sidebar
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
diff --git a/src/Artemis.UI/Services/UpdateService.cs b/src/Artemis.UI/Services/UpdateService.cs
index 35dada594..5e3e481ee 100644
--- a/src/Artemis.UI/Services/UpdateService.cs
+++ b/src/Artemis.UI/Services/UpdateService.cs
@@ -28,7 +28,6 @@ namespace Artemis.UI.Services
private const double UpdateCheckInterval = 3600000; // once per hour
private const string ApiUrl = "https://dev.azure.com/artemis-rgb/Artemis/_apis/";
- private readonly PluginSetting _autoInstallUpdates;
private readonly PluginSetting _checkForUpdates;
private readonly IDialogService _dialogService;
private readonly ILogger _logger;
@@ -42,7 +41,6 @@ namespace Artemis.UI.Services
_windowService.MainWindowOpened += WindowServiceOnMainWindowOpened;
_checkForUpdates = settingsService.GetSetting("UI.CheckForUpdates", true);
- _autoInstallUpdates = settingsService.GetSetting("UI.AutoInstallUpdates", false);
_checkForUpdates.SettingChanged += CheckForUpdatesOnSettingChanged;
Timer timer = new(UpdateCheckInterval);
@@ -136,18 +134,7 @@ namespace Artemis.UI.Services
if (_windowService.IsMainWindowOpen)
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
- {
// If auto-install is disabled and the window is closed, best we can do is notify the user and stop.
new ToastContentBuilder()
.AddText("New version available", AdaptiveTextStyle.Header)
@@ -155,7 +142,6 @@ namespace Artemis.UI.Services
.AddButton("Update", ToastActivationType.Background, "update")
.AddButton("Later", ToastActivationType.Background, "later")
.Show(t => t.Activated += TOnActivated);
- }
return true;
}