mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Conditions - Moved non-list conditions to new paths API
Conditions - Move list conditions to new paths API (WIP)
This commit is contained in:
parent
9417332a07
commit
725bb2a128
@ -15,7 +15,7 @@ namespace Artemis.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the parent of this part
|
/// Gets the parent of this part
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataModelConditionPart Parent { get; internal set; }
|
public DataModelConditionPart? Parent { get; internal set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the children of this part
|
/// Gets the children of this part
|
||||||
|
|||||||
@ -95,6 +95,7 @@ namespace Artemis.Core
|
|||||||
if (!typeof(IList).IsAssignableFrom(listType))
|
if (!typeof(IList).IsAssignableFrom(listType))
|
||||||
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{newPath}'");
|
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{newPath}'");
|
||||||
|
|
||||||
|
ListPath = newPath;
|
||||||
ListType = listType;
|
ListType = listType;
|
||||||
IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string);
|
IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Linq.Expressions;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core.DataModelExpansions;
|
||||||
using Artemis.Storage.Entities.Profile.Abstract;
|
using Artemis.Storage.Entities.Profile.Abstract;
|
||||||
@ -41,8 +39,6 @@ namespace Artemis.Core
|
|||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DataModelConditionListPredicateEntity Entity { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the predicate type
|
/// Gets or sets the predicate type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -68,6 +64,8 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public object? RightStaticValue { get; private set; }
|
public object? RightStaticValue { get; private set; }
|
||||||
|
|
||||||
|
internal DataModelConditionListPredicateEntity Entity { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the left side of the predicate
|
/// Updates the left side of the predicate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -80,11 +78,12 @@ namespace Artemis.Core
|
|||||||
throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
|
throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
|
||||||
|
|
||||||
LeftPath?.Dispose();
|
LeftPath?.Dispose();
|
||||||
LeftPath = new DataModelPath(new ListPredicateWrapperDataModel(), path);
|
LeftPath = DataModelConditionList.ListType != null
|
||||||
|
? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path)
|
||||||
|
: null;
|
||||||
|
|
||||||
ValidateOperator();
|
ValidateOperator();
|
||||||
ValidateRightSide();
|
ValidateRightSide();
|
||||||
CreateExpression();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -99,9 +98,9 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
PredicateType = ListRightSideType.DynamicList;
|
PredicateType = ListRightSideType.DynamicList;
|
||||||
RightPath?.Dispose();
|
RightPath?.Dispose();
|
||||||
RightPath = new DataModelPath(new ListPredicateWrapperDataModel(), path);
|
RightPath = DataModelConditionList.ListType != null
|
||||||
|
? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path)
|
||||||
CreateExpression();
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -118,37 +117,32 @@ namespace Artemis.Core
|
|||||||
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
throw new ArtemisCoreException("If path is provided, a data model is also required");
|
||||||
|
|
||||||
if (dataModel != null)
|
if (dataModel != null)
|
||||||
{
|
|
||||||
if (!dataModel.ContainsPath(path))
|
if (!dataModel.ContainsPath(path))
|
||||||
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
|
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
|
||||||
}
|
|
||||||
|
|
||||||
PredicateType = ListRightSideType.Dynamic;
|
PredicateType = ListRightSideType.Dynamic;
|
||||||
RightPath?.Dispose();
|
RightPath?.Dispose();
|
||||||
RightPath = new DataModelPath(dataModel, path);
|
RightPath = new DataModelPath(dataModel, path);
|
||||||
|
|
||||||
CreateExpression();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the right side of the predicate, makes the predicate static and re-compiles the expression
|
/// Updates the right side of the predicate, makes the predicate static and re-compiles the expression
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="staticValue">The right side value to use</param>
|
/// <param name="staticValue">The right side value to use</param>
|
||||||
public void UpdateRightSideStatic(object staticValue)
|
public void UpdateRightSideStatic(object? staticValue)
|
||||||
{
|
{
|
||||||
PredicateType = ListRightSideType.Static;
|
PredicateType = ListRightSideType.Static;
|
||||||
RightPath?.Dispose();
|
RightPath?.Dispose();
|
||||||
RightPath = null;
|
RightPath = null;
|
||||||
|
|
||||||
SetStaticValue(staticValue);
|
SetStaticValue(staticValue);
|
||||||
CreateExpression();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the operator of the predicate and re-compiles the expression
|
/// Updates the operator of the predicate and re-compiles the expression
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="conditionOperator"></param>
|
/// <param name="conditionOperator"></param>
|
||||||
public void UpdateOperator(ConditionOperator conditionOperator)
|
public void UpdateOperator(ConditionOperator? conditionOperator)
|
||||||
{
|
{
|
||||||
if (conditionOperator == null)
|
if (conditionOperator == null)
|
||||||
{
|
{
|
||||||
@ -170,8 +164,6 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
if (conditionOperator.SupportsType(leftType))
|
if (conditionOperator.SupportsType(leftType))
|
||||||
Operator = conditionOperator;
|
Operator = conditionOperator;
|
||||||
|
|
||||||
CreateExpression();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -205,6 +197,22 @@ namespace Artemis.Core
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
|
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
|
LeftPath?.Dispose();
|
||||||
|
RightPath?.Dispose();
|
||||||
|
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
internal override bool EvaluateObject(object target)
|
internal override bool EvaluateObject(object target)
|
||||||
{
|
{
|
||||||
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
||||||
@ -254,10 +262,12 @@ namespace Artemis.Core
|
|||||||
internal override void Save()
|
internal override void Save()
|
||||||
{
|
{
|
||||||
Entity.PredicateType = (int) PredicateType;
|
Entity.PredicateType = (int) PredicateType;
|
||||||
Entity.LeftPropertyPath = LeftPropertyPath;
|
|
||||||
|
|
||||||
Entity.RightDataModelGuid = RightDataModel?.PluginInfo?.Guid;
|
LeftPath?.Save();
|
||||||
Entity.RightPropertyPath = RightPropertyPath;
|
Entity.LeftPath = LeftPath?.Entity;
|
||||||
|
RightPath?.Save();
|
||||||
|
Entity.RightPath = RightPath?.Entity;
|
||||||
|
|
||||||
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
||||||
|
|
||||||
if (Operator != null)
|
if (Operator != null)
|
||||||
@ -274,19 +284,12 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void ApplyParentList()
|
private void ApplyParentList()
|
||||||
{
|
{
|
||||||
DataModelConditionPart current = Parent;
|
DataModelConditionPart? current = Parent;
|
||||||
|
|
||||||
while (current != null)
|
while (current != null)
|
||||||
{
|
{
|
||||||
if (current is DataModelConditionList parentList)
|
if (current is DataModelConditionList parentList)
|
||||||
{
|
{
|
||||||
DataModelConditionList = parentList;
|
DataModelConditionList = parentList;
|
||||||
|
|
||||||
if (LeftPropertyPath != null && !ListContainsInnerPath(LeftPropertyPath))
|
|
||||||
LeftPropertyPath = null;
|
|
||||||
if (RightPropertyPath != null && !ListContainsInnerPath(RightPropertyPath))
|
|
||||||
RightPropertyPath = null;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,46 +302,44 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
|
|
||||||
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
|
|
||||||
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
|
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
// Left side
|
// Left side
|
||||||
if (Entity.LeftPropertyPath != null && ListContainsInnerPath(Entity.LeftPropertyPath))
|
if (Entity.LeftPath != null)
|
||||||
UpdateLeftSide(Entity.LeftPropertyPath);
|
{
|
||||||
|
LeftPath = DataModelConditionList.ListType != null
|
||||||
|
? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), Entity.LeftPath)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
// Operator
|
// Operator
|
||||||
if (Entity.OperatorPluginGuid != null)
|
if (Entity.OperatorPluginGuid != null)
|
||||||
{
|
{
|
||||||
ConditionOperator conditionOperator = ConditionOperatorStore.Get(Entity.OperatorPluginGuid.Value, Entity.OperatorType)?.ConditionOperator;
|
ConditionOperator? conditionOperator = ConditionOperatorStore.Get(Entity.OperatorPluginGuid.Value, Entity.OperatorType)?.ConditionOperator;
|
||||||
if (conditionOperator != null)
|
if (conditionOperator != null)
|
||||||
UpdateOperator(conditionOperator);
|
UpdateOperator(conditionOperator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right side dynamic
|
// Right side dynamic
|
||||||
if (PredicateType == ListRightSideType.Dynamic && Entity.RightDataModelGuid != null && Entity.RightPropertyPath != null)
|
if (PredicateType == ListRightSideType.Dynamic && Entity.RightPath != null)
|
||||||
{
|
RightPath = new DataModelPath(null, Entity.RightPath);
|
||||||
DataModel dataModel = DataModelStore.Get(Entity.RightDataModelGuid.Value)?.DataModel;
|
|
||||||
if (dataModel != null && dataModel.ContainsPath(Entity.RightPropertyPath))
|
|
||||||
UpdateRightSideDynamic(dataModel, Entity.RightPropertyPath);
|
|
||||||
}
|
|
||||||
// Right side dynamic inside the list
|
// Right side dynamic inside the list
|
||||||
else if (PredicateType == ListRightSideType.DynamicList && Entity.RightPropertyPath != null)
|
else if (PredicateType == ListRightSideType.DynamicList && Entity.RightPath != null)
|
||||||
{
|
{
|
||||||
if (ListContainsInnerPath(Entity.RightPropertyPath))
|
RightPath = DataModelConditionList.ListType != null
|
||||||
UpdateRightSideDynamic(Entity.RightPropertyPath);
|
? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), Entity.RightPath)
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
// Right side static
|
// Right side static
|
||||||
else if (PredicateType == ListRightSideType.Static && Entity.RightStaticValue != null)
|
else if (PredicateType == ListRightSideType.Static && Entity.RightStaticValue != null)
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (LeftPropertyPath != null)
|
if (LeftPath != null && LeftPath.IsValid)
|
||||||
{
|
{
|
||||||
// Use the left side type so JSON.NET has a better idea what to do
|
// Use the left side type so JSON.NET has a better idea what to do
|
||||||
Type leftSideType = GetTypeAtInnerPath(LeftPropertyPath);
|
Type leftSideType = LeftPath.GetPropertyType()!;
|
||||||
object rightSideValue;
|
object? rightSideValue;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -363,73 +364,62 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
DeserializationLogger.LogListPredicateDeserializationFailure(this, e);
|
DeserializationLogger.LogListPredicateDeserializationFailure(this, e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateExpression()
|
|
||||||
{
|
|
||||||
if (Operator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If the operator does not support a right side, create a static expression because the right side will simply be null
|
|
||||||
if (PredicateType == ListRightSideType.DynamicList && Operator.SupportsRightSide)
|
|
||||||
CreateDynamicListAccessors();
|
|
||||||
else if (PredicateType == ListRightSideType.Dynamic && Operator.SupportsRightSide)
|
|
||||||
CreateDynamicAccessors();
|
|
||||||
else
|
|
||||||
CreateStaticAccessors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateOperator()
|
private void ValidateOperator()
|
||||||
{
|
{
|
||||||
if (LeftPropertyPath == null || Operator == null)
|
if (LeftPath == null || !LeftPath.IsValid || Operator == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Type leftSideType = GetTypeAtInnerPath(LeftPropertyPath);
|
Type leftType = LeftPath.GetPropertyType()!;
|
||||||
if (!Operator.SupportsType(leftSideType))
|
if (!Operator.SupportsType(leftType))
|
||||||
Operator = null;
|
Operator = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateRightSide()
|
private void ValidateRightSide()
|
||||||
{
|
{
|
||||||
Type leftSideType = GetTypeAtInnerPath(LeftPropertyPath);
|
Type? leftType = LeftPath?.GetPropertyType();
|
||||||
if (PredicateType == ListRightSideType.Dynamic)
|
if (PredicateType == ListRightSideType.Dynamic)
|
||||||
{
|
{
|
||||||
if (RightDataModel == null)
|
if (RightPath == null || !RightPath.IsValid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Type rightSideType = RightDataModel.GetTypeAtPath(RightPropertyPath);
|
Type rightSideType = RightPath.GetPropertyType()!;
|
||||||
if (!leftSideType.IsCastableFrom(rightSideType))
|
if (leftType != null && !leftType.IsCastableFrom(rightSideType))
|
||||||
UpdateRightSideDynamic(null, null);
|
UpdateRightSideDynamic(null, null);
|
||||||
}
|
}
|
||||||
else if (PredicateType == ListRightSideType.DynamicList)
|
else if (PredicateType == ListRightSideType.DynamicList)
|
||||||
{
|
{
|
||||||
if (RightPropertyPath == null)
|
if (RightPath == null || !RightPath.IsValid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Type rightSideType = GetTypeAtInnerPath(RightPropertyPath);
|
Type rightSideType = RightPath.GetPropertyType()!;
|
||||||
if (!leftSideType.IsCastableFrom(rightSideType))
|
if (leftType != null && !leftType.IsCastableFrom(rightSideType))
|
||||||
UpdateRightSideDynamic(null);
|
UpdateRightSideDynamic(null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (RightStaticValue != null && leftSideType.IsCastableFrom(RightStaticValue.GetType()))
|
if (RightStaticValue != null && (leftType == null || leftType.IsCastableFrom(RightStaticValue.GetType())))
|
||||||
UpdateRightSideStatic(RightStaticValue);
|
UpdateRightSideStatic(RightStaticValue);
|
||||||
else
|
else
|
||||||
UpdateRightSideStatic(null);
|
UpdateRightSideStatic(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetStaticValue(object staticValue)
|
private void SetStaticValue(object? staticValue)
|
||||||
{
|
{
|
||||||
|
RightPath?.Dispose();
|
||||||
|
RightPath = null;
|
||||||
|
|
||||||
// If the left side is empty simply apply the value, any validation will wait
|
// If the left side is empty simply apply the value, any validation will wait
|
||||||
if (LeftPropertyPath == null)
|
if (LeftPath == null || !LeftPath.IsValid)
|
||||||
{
|
{
|
||||||
RightStaticValue = staticValue;
|
RightStaticValue = staticValue;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type leftSideType = GetTypeAtInnerPath(LeftPropertyPath);
|
// If the left path is valid we can expect a type
|
||||||
|
Type leftSideType = LeftPath.GetPropertyType()!;
|
||||||
|
|
||||||
// If not null ensure the types match and if not, convert it
|
// If not null ensure the types match and if not, convert it
|
||||||
if (staticValue != null && staticValue.GetType() == leftSideType)
|
if (staticValue != null && staticValue.GetType() == leftSideType)
|
||||||
@ -448,107 +438,12 @@ namespace Artemis.Core
|
|||||||
if (!(path.Target is ListPredicateWrapperDataModel wrapper))
|
if (!(path.Target is ListPredicateWrapperDataModel wrapper))
|
||||||
throw new ArtemisCoreException("Data model condition list predicate has a path with an invalid target");
|
throw new ArtemisCoreException("Data model condition list predicate has a path with an invalid target");
|
||||||
|
|
||||||
wrapper.Value = target;
|
wrapper.UntypedValue = target;
|
||||||
return path.GetValue();
|
return path.GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateDynamicListAccessors()
|
|
||||||
{
|
|
||||||
if (LeftPropertyPath == null || RightPropertyPath == null || Operator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// List accessors share the same parameter because a list always contains one item per entry
|
|
||||||
ParameterExpression leftSideParameter = Expression.Parameter(typeof(object), "listItem");
|
|
||||||
Expression leftSideAccessor = CreateListAccessor(LeftPropertyPath, leftSideParameter);
|
|
||||||
Expression rightSideAccessor = CreateListAccessor(RightPropertyPath, leftSideParameter);
|
|
||||||
|
|
||||||
// A conversion may be required if the types differ
|
|
||||||
// This can cause issues if the DataModelConditionOperator wasn't accurate in it's supported types but that is not a concern here
|
|
||||||
if (rightSideAccessor.Type != leftSideAccessor.Type)
|
|
||||||
rightSideAccessor = Expression.Convert(rightSideAccessor, leftSideAccessor.Type);
|
|
||||||
|
|
||||||
LeftSideAccessor = Expression.Lambda<Func<object, object>>(leftSideAccessor, leftSideParameter).Compile();
|
|
||||||
RightSideAccessor = Expression.Lambda<Func<object, object>>(rightSideAccessor, leftSideParameter).Compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateDynamicAccessors()
|
|
||||||
{
|
|
||||||
if (LeftPropertyPath == null || RightPropertyPath == null || RightDataModel == null || Operator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// List accessors share the same parameter because a list always contains one item per entry
|
|
||||||
ParameterExpression leftSideParameter = Expression.Parameter(typeof(object), "listItem");
|
|
||||||
Expression leftSideAccessor = CreateListAccessor(LeftPropertyPath, leftSideParameter);
|
|
||||||
Expression rightSideAccessor = ExpressionUtilities.CreateDataModelAccessor(RightDataModel, RightPropertyPath, "right", out ParameterExpression rightSideParameter);
|
|
||||||
|
|
||||||
// A conversion may be required if the types differ
|
|
||||||
// This can cause issues if the DataModelConditionOperator wasn't accurate in it's supported types but that is not a concern here
|
|
||||||
if (rightSideAccessor.Type != leftSideAccessor.Type)
|
|
||||||
rightSideAccessor = Expression.Convert(rightSideAccessor, leftSideAccessor.Type);
|
|
||||||
|
|
||||||
LeftSideAccessor = Expression.Lambda<Func<object, object>>(leftSideAccessor, leftSideParameter).Compile();
|
|
||||||
RightSideAccessor = Expression.Lambda<Func<object, object>>(rightSideAccessor, rightSideParameter).Compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateStaticAccessors()
|
|
||||||
{
|
|
||||||
if (!DataModelConditionList.IsPrimitiveList && LeftPropertyPath == null || Operator == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// List accessors share the same parameter because a list always contains one item per entry
|
|
||||||
ParameterExpression leftSideParameter = Expression.Parameter(typeof(object), "listItem");
|
|
||||||
Expression leftSideAccessor = DataModelConditionList.IsPrimitiveList
|
|
||||||
? Expression.Convert(leftSideParameter, DataModelConditionList.ListType)
|
|
||||||
: CreateListAccessor(LeftPropertyPath, leftSideParameter);
|
|
||||||
|
|
||||||
LeftSideAccessor = Expression.Lambda<Func<object, object>>(leftSideAccessor, leftSideParameter).Compile();
|
|
||||||
RightSideAccessor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Expression CreateListAccessor(string path, ParameterExpression listParameter)
|
|
||||||
{
|
|
||||||
// Create an expression that checks every part of the path for null
|
|
||||||
// In the same iteration, create the accessor
|
|
||||||
Expression source = Expression.Convert(listParameter, DataModelConditionList.ListType);
|
|
||||||
return ExpressionUtilities.CreateNullCheckedAccessor(source, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region IDisposable
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
|
||||||
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
|
||||||
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
|
|
||||||
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
|
|
||||||
|
|
||||||
LeftPath?.Dispose();
|
|
||||||
RightPath?.Dispose();
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
|
|
||||||
private void DataModelStoreOnDataModelAdded(object sender, DataModelStoreEvent e)
|
|
||||||
{
|
|
||||||
DataModel dataModel = e.Registration.DataModel;
|
|
||||||
if (dataModel.PluginInfo.Guid == Entity.RightDataModelGuid && dataModel.ContainsPath(Entity.RightPropertyPath))
|
|
||||||
UpdateRightSideDynamic(dataModel, Entity.RightPropertyPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DataModelStoreOnDataModelRemoved(object sender, DataModelStoreEvent e)
|
|
||||||
{
|
|
||||||
if (RightDataModel == e.Registration.DataModel)
|
|
||||||
{
|
|
||||||
RightSideAccessor = null;
|
|
||||||
RightDataModel = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConditionOperatorStoreOnConditionOperatorAdded(object sender, ConditionOperatorStoreEvent e)
|
private void ConditionOperatorStoreOnConditionOperatorAdded(object sender, ConditionOperatorStoreEvent e)
|
||||||
{
|
{
|
||||||
ConditionOperator conditionOperator = e.Registration.ConditionOperator;
|
ConditionOperator conditionOperator = e.Registration.ConditionOperator;
|
||||||
|
|||||||
@ -240,8 +240,11 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
||||||
|
|
||||||
Entity.OperatorPluginGuid = Operator?.PluginInfo?.Guid;
|
if (Operator != null)
|
||||||
Entity.OperatorType = Operator?.GetType().Name;
|
{
|
||||||
|
Entity.OperatorPluginGuid = Operator.PluginInfo.Guid;
|
||||||
|
Entity.OperatorType = Operator.GetType().Name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Initialize()
|
internal void Initialize()
|
||||||
@ -250,7 +253,8 @@ namespace Artemis.Core
|
|||||||
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
// Left side
|
// Left side
|
||||||
if (Entity.LeftPath != null) LeftPath = new DataModelPath(null, Entity.LeftPath);
|
if (Entity.LeftPath != null)
|
||||||
|
LeftPath = new DataModelPath(null, Entity.LeftPath);
|
||||||
|
|
||||||
// Operator
|
// Operator
|
||||||
if (Entity.OperatorPluginGuid != null)
|
if (Entity.OperatorPluginGuid != null)
|
||||||
|
|||||||
@ -1,9 +1,24 @@
|
|||||||
using Artemis.Core.DataModelExpansions;
|
using System;
|
||||||
|
using Artemis.Core.DataModelExpansions;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
internal class ListPredicateWrapperDataModel : DataModel
|
internal class ListPredicateWrapperDataModel<T> : ListPredicateWrapperDataModel
|
||||||
{
|
{
|
||||||
public object Value { get; set; }
|
public T Value => (UntypedValue is T typedValue ? typedValue : default)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class ListPredicateWrapperDataModel : DataModel
|
||||||
|
{
|
||||||
|
public object? UntypedValue { get; set; }
|
||||||
|
|
||||||
|
public static ListPredicateWrapperDataModel Create(Type type)
|
||||||
|
{
|
||||||
|
object? instance = Activator.CreateInstance(typeof(ListPredicateWrapperDataModel<>).MakeGenericType(type));
|
||||||
|
if (instance == null)
|
||||||
|
throw new ArtemisCoreException($"Failed to create an instance of ListPredicateWrapperDataModel<T> for type {type.Name}");
|
||||||
|
|
||||||
|
return (ListPredicateWrapperDataModel) instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,9 +29,9 @@ namespace Artemis.Core
|
|||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
exception,
|
exception,
|
||||||
"Failed to deserialize display condition list predicate {list} => {left} {operator} {right}",
|
"Failed to deserialize display condition list predicate {list} => {left} {operator} {right}",
|
||||||
dataModelConditionPredicate.Entity.LeftPropertyPath,
|
dataModelConditionPredicate.Entity.LeftPath?.Path,
|
||||||
dataModelConditionPredicate.Entity.OperatorType,
|
dataModelConditionPredicate.Entity.OperatorType,
|
||||||
dataModelConditionPredicate.Entity.RightPropertyPath
|
dataModelConditionPredicate.Entity.RightPath?.Path
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,15 +7,14 @@ namespace Artemis.Storage.Entities.Profile.Conditions
|
|||||||
{
|
{
|
||||||
public int PredicateType { get; set; }
|
public int PredicateType { get; set; }
|
||||||
|
|
||||||
public string LeftPropertyPath { get; set; }
|
public DataModelPathEntity LeftPath { get; set; }
|
||||||
|
public DataModelPathEntity RightPath { get; set; }
|
||||||
public Guid? RightDataModelGuid { get; set; }
|
|
||||||
public string RightPropertyPath { get; set; }
|
|
||||||
|
|
||||||
// Stored as a string to be able to control serialization and deserialization ourselves
|
// Stored as a string to be able to control serialization and deserialization ourselves
|
||||||
public string RightStaticValue { get; set; }
|
public string RightStaticValue { get; set; }
|
||||||
|
|
||||||
public string OperatorType { get; set; }
|
public string OperatorType { get; set; }
|
||||||
public Guid? OperatorPluginGuid { get; set; }
|
public Guid? OperatorPluginGuid { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
@ -10,9 +10,9 @@ namespace Artemis.UI.Shared
|
|||||||
private int _index;
|
private int _index;
|
||||||
private Type _listType;
|
private Type _listType;
|
||||||
|
|
||||||
public DataModelListPropertiesViewModel(DataModel dataModel, object listItem) : base(null, null, null)
|
public DataModelListPropertiesViewModel(object listItem) : base(null, null, null)
|
||||||
{
|
{
|
||||||
DataModel = dataModel;
|
DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType());
|
||||||
ListType = listItem.GetType();
|
ListType = listItem.GetType();
|
||||||
DisplayValue = listItem;
|
DisplayValue = listItem;
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ namespace Artemis.UI.Shared
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ListType = DisplayValue.GetType();
|
ListType = DisplayValue.GetType();
|
||||||
PopulateProperties(dataModelUIService, DisplayValue);
|
PopulateProperties(dataModelUIService);
|
||||||
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
|
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children)
|
||||||
dataModelVisualizationViewModel.Update(dataModelUIService);
|
dataModelVisualizationViewModel.Update(dataModelUIService);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core.DataModelExpansions;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared
|
namespace Artemis.UI.Shared
|
||||||
@ -9,17 +9,17 @@ namespace Artemis.UI.Shared
|
|||||||
private int _index;
|
private int _index;
|
||||||
private Type _listType;
|
private Type _listType;
|
||||||
|
|
||||||
public DataModelListPropertyViewModel(DataModel dataModel, object listItem, DataModelDisplayViewModel displayViewModel) : base(null, null, null)
|
public DataModelListPropertyViewModel(object listItem, DataModelDisplayViewModel displayViewModel) : base(null, null, null)
|
||||||
{
|
{
|
||||||
DataModel = dataModel;
|
DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType());
|
||||||
ListType = listItem.GetType();
|
ListType = listItem.GetType();
|
||||||
DisplayValue = listItem;
|
DisplayValue = listItem;
|
||||||
DisplayViewModel = displayViewModel;
|
DisplayViewModel = displayViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataModelListPropertyViewModel(DataModel dataModel, object listItem) : base(null, null, null)
|
public DataModelListPropertyViewModel(object listItem) : base(null, null, null)
|
||||||
{
|
{
|
||||||
DataModel = dataModel;
|
DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType());
|
||||||
ListType = listItem.GetType();
|
ListType = listItem.GetType();
|
||||||
DisplayValue = listItem;
|
DisplayValue = listItem;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,6 @@ namespace Artemis.UI.Shared
|
|||||||
{
|
{
|
||||||
private string _count;
|
private string _count;
|
||||||
private IList _list;
|
private IList _list;
|
||||||
private DataModelVisualizationViewModel _listTypePropertyViewModel;
|
|
||||||
|
|
||||||
internal DataModelListViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath)
|
internal DataModelListViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath)
|
||||||
{
|
{
|
||||||
@ -44,8 +43,6 @@ namespace Artemis.UI.Shared
|
|||||||
// Put an empty value into the list type property view model
|
// Put an empty value into the list type property view model
|
||||||
if (viewModel is DataModelListPropertiesViewModel dataModelListClassViewModel)
|
if (viewModel is DataModelListPropertiesViewModel dataModelListClassViewModel)
|
||||||
{
|
{
|
||||||
dataModelListClassViewModel.DisplayValue = Activator.CreateInstance(dataModelListClassViewModel.ListType);
|
|
||||||
dataModelListClassViewModel.Update(dataModelUIService);
|
|
||||||
return dataModelListClassViewModel;
|
return dataModelListClassViewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,13 +106,13 @@ namespace Artemis.UI.Shared
|
|||||||
// If a display VM was found, prefer to use that in any case
|
// If a display VM was found, prefer to use that in any case
|
||||||
DataModelDisplayViewModel typeViewModel = dataModelUIService.GetDataModelDisplayViewModel(listType);
|
DataModelDisplayViewModel typeViewModel = dataModelUIService.GetDataModelDisplayViewModel(listType);
|
||||||
if (typeViewModel != null)
|
if (typeViewModel != null)
|
||||||
return new DataModelListPropertyViewModel(DataModel, listItem, typeViewModel);
|
return new DataModelListPropertyViewModel(listItem, typeViewModel);
|
||||||
// For primitives, create a property view model, it may be null that is fine
|
// For primitives, create a property view model, it may be null that is fine
|
||||||
if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string))
|
if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string))
|
||||||
return new DataModelListPropertyViewModel(DataModel, listItem);
|
return new DataModelListPropertyViewModel(listItem);
|
||||||
// For other value types create a child view model
|
// For other value types create a child view model
|
||||||
if (listType.IsClass || listType.IsStruct())
|
if (listType.IsClass || listType.IsStruct())
|
||||||
return new DataModelListPropertiesViewModel(DataModel, listItem);
|
return new DataModelListPropertiesViewModel(listItem);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace Artemis.UI.Shared
|
|||||||
public override void Update(IDataModelUIService dataModelUIService)
|
public override void Update(IDataModelUIService dataModelUIService)
|
||||||
{
|
{
|
||||||
// Always populate properties
|
// Always populate properties
|
||||||
PopulateProperties(dataModelUIService, null);
|
PopulateProperties(dataModelUIService);
|
||||||
|
|
||||||
// Only update children if the parent is expanded
|
// Only update children if the parent is expanded
|
||||||
if (Parent != null && !Parent.IsVisualizationExpanded && !Parent.IsRootViewModel)
|
if (Parent != null && !Parent.IsVisualizationExpanded && !Parent.IsRootViewModel)
|
||||||
|
|||||||
@ -125,7 +125,7 @@ namespace Artemis.UI.Shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the type couldn't be retrieved either way, assume false
|
// If the type couldn't be retrieved either way, assume false
|
||||||
Type type = DataModelPath.GetPropertyType();
|
Type type = DataModelPath?.GetPropertyType();
|
||||||
if (type == null)
|
if (type == null)
|
||||||
{
|
{
|
||||||
IsMatchingFilteredTypes = false;
|
IsMatchingFilteredTypes = false;
|
||||||
@ -178,18 +178,12 @@ namespace Artemis.UI.Shared
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void PopulateProperties(IDataModelUIService dataModelUIService, object overrideValue)
|
internal void PopulateProperties(IDataModelUIService dataModelUIService)
|
||||||
{
|
{
|
||||||
if (IsRootViewModel && overrideValue == null)
|
if (IsRootViewModel)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Type modelType;
|
Type modelType = Parent.IsRootViewModel ? DataModel.GetType() : DataModelPath.GetPropertyType();
|
||||||
if (overrideValue != null)
|
|
||||||
modelType = overrideValue.GetType();
|
|
||||||
else if (Parent.IsRootViewModel)
|
|
||||||
modelType = DataModel.GetType();
|
|
||||||
else
|
|
||||||
modelType = DataModelPath.GetPropertyType();
|
|
||||||
|
|
||||||
// Add missing static children
|
// Add missing static children
|
||||||
foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||||
@ -200,17 +194,13 @@ namespace Artemis.UI.Shared
|
|||||||
if (propertyInfo.GetCustomAttribute<DataModelIgnoreAttribute>() != null)
|
if (propertyInfo.GetCustomAttribute<DataModelIgnoreAttribute>() != null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
DataModelVisualizationViewModel child = CreateChild(dataModelUIService, childPath, GetChildDepth(), overrideValue);
|
DataModelVisualizationViewModel child = CreateChild(dataModelUIService, childPath, GetChildDepth());
|
||||||
if (child != null)
|
if (child != null)
|
||||||
Children.Add(child);
|
Children.Add(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove static children that should be hidden
|
// Remove static children that should be hidden
|
||||||
ReadOnlyCollection<PropertyInfo> hiddenProperties;
|
ReadOnlyCollection<PropertyInfo> hiddenProperties = DataModel.GetHiddenProperties();
|
||||||
if (overrideValue != null && overrideValue is DataModel overrideValueDataModel)
|
|
||||||
hiddenProperties = overrideValueDataModel.GetHiddenProperties();
|
|
||||||
else
|
|
||||||
hiddenProperties = DataModel.GetHiddenProperties();
|
|
||||||
foreach (PropertyInfo hiddenProperty in hiddenProperties)
|
foreach (PropertyInfo hiddenProperty in hiddenProperties)
|
||||||
{
|
{
|
||||||
string childPath = AppendToPath(hiddenProperty.Name);
|
string childPath = AppendToPath(hiddenProperty.Name);
|
||||||
@ -220,11 +210,7 @@ namespace Artemis.UI.Shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add missing dynamic children
|
// Add missing dynamic children
|
||||||
object value;
|
object value = Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue();
|
||||||
if (overrideValue != null)
|
|
||||||
value = overrideValue;
|
|
||||||
else
|
|
||||||
value = Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue();
|
|
||||||
if (value is DataModel dataModel)
|
if (value is DataModel dataModel)
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<string, DataModel> kvp in dataModel.DynamicDataModels)
|
foreach (KeyValuePair<string, DataModel> kvp in dataModel.DynamicDataModels)
|
||||||
@ -233,7 +219,7 @@ namespace Artemis.UI.Shared
|
|||||||
if (Children.Any(c => c.Path != null && c.Path.Equals(childPath)))
|
if (Children.Any(c => c.Path != null && c.Path.Equals(childPath)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
DataModelVisualizationViewModel child = CreateChild(dataModelUIService, childPath, GetChildDepth(), overrideValue);
|
DataModelVisualizationViewModel child = CreateChild(dataModelUIService, childPath, GetChildDepth());
|
||||||
if (child != null)
|
if (child != null)
|
||||||
Children.Add(child);
|
Children.Add(child);
|
||||||
}
|
}
|
||||||
@ -245,12 +231,12 @@ namespace Artemis.UI.Shared
|
|||||||
Children.RemoveRange(toRemoveDynamic);
|
Children.RemoveRange(toRemoveDynamic);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataModelVisualizationViewModel CreateChild(IDataModelUIService dataModelUIService, string path, int depth, object overrideValue)
|
private DataModelVisualizationViewModel CreateChild(IDataModelUIService dataModelUIService, string path, int depth)
|
||||||
{
|
{
|
||||||
if (depth > MaxDepth)
|
if (depth > MaxDepth)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
DataModelPath dataModelPath = new DataModelPath(overrideValue ?? DataModel, path);
|
DataModelPath dataModelPath = new DataModelPath(DataModel, path);
|
||||||
if (!dataModelPath.IsValid)
|
if (!dataModelPath.IsValid)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|||||||
@ -79,18 +79,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
|
|
||||||
public DelegateCommand SelectOperatorCommand { get; }
|
public DelegateCommand SelectOperatorCommand { get; }
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!_isPrimitiveList)
|
|
||||||
{
|
|
||||||
LeftSideSelectionViewModel.PropertySelected -= LeftSideOnPropertySelected;
|
|
||||||
LeftSideSelectionViewModel.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
DisposeRightSideDynamic();
|
|
||||||
DisposeRightSideStatic();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Delete()
|
public override void Delete()
|
||||||
{
|
{
|
||||||
base.Delete();
|
base.Delete();
|
||||||
@ -123,7 +111,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
Guid? listDataModelGuid = DataModelConditionListPredicate.DataModelConditionList.ListPath.DataModelGuid;
|
Guid? listDataModelGuid = DataModelConditionListPredicate.DataModelConditionList.ListPath?.DataModelGuid;
|
||||||
if (listDataModelGuid == null)
|
if (listDataModelGuid == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -132,7 +120,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
|
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
|
||||||
LeftSideSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(71, 108, 188));
|
LeftSideSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(71, 108, 188));
|
||||||
LeftSideSelectionViewModel.SelectedPropertyViewModel = LeftSideSelectionViewModel.DataModelViewModel.GetChildByPath(
|
LeftSideSelectionViewModel.SelectedPropertyViewModel = LeftSideSelectionViewModel.DataModelViewModel.GetChildByPath(
|
||||||
listDataModelGuid.Value, DataModelConditionListPredicate.LeftPropertyPath
|
listDataModelGuid.Value, DataModelConditionListPredicate.DataModelConditionList.ListPath.Path
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,14 +130,20 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
|
|
||||||
// Get the supported operators
|
// Get the supported operators
|
||||||
Operators.Clear();
|
Operators.Clear();
|
||||||
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType ?? typeof(object)));
|
||||||
if (DataModelConditionListPredicate.Operator == null)
|
if (DataModelConditionListPredicate.Operator == null)
|
||||||
DataModelConditionListPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
DataModelConditionListPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType ?? typeof(object))));
|
||||||
SelectedOperator = DataModelConditionListPredicate.Operator;
|
SelectedOperator = DataModelConditionListPredicate.Operator;
|
||||||
|
if (SelectedOperator == null || !SelectedOperator.SupportsRightSide)
|
||||||
|
{
|
||||||
|
DisposeRightSideStatic();
|
||||||
|
DisposeRightSideDynamic();
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the right side has the proper VM
|
// Ensure the right side has the proper VM
|
||||||
if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic ||
|
if ((DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic ||
|
||||||
DataModelConditionListPredicate.PredicateType == ListRightSideType.DynamicList)
|
DataModelConditionListPredicate.PredicateType == ListRightSideType.DynamicList) &&
|
||||||
|
SelectedOperator.SupportsRightSide)
|
||||||
{
|
{
|
||||||
DisposeRightSideStatic();
|
DisposeRightSideStatic();
|
||||||
if (RightSideSelectionViewModel == null)
|
if (RightSideSelectionViewModel == null)
|
||||||
@ -164,20 +158,16 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
|
|
||||||
RightSideSelectionViewModel.FilterTypes = new[] {leftSideType};
|
RightSideSelectionViewModel.FilterTypes = new[] {leftSideType};
|
||||||
if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic)
|
if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic)
|
||||||
{
|
|
||||||
RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
|
RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
|
||||||
DataModelConditionListPredicate.RightDataModel,
|
DataModelConditionListPredicate.RightPath?.Target,
|
||||||
DataModelConditionListPredicate.RightPropertyPath
|
DataModelConditionListPredicate.RightPath?.Path
|
||||||
);
|
);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
RightSideSelectionViewModel.SelectedPropertyViewModel = RightSideSelectionViewModel.DataModelViewModel.GetChildByPath(
|
RightSideSelectionViewModel.SelectedPropertyViewModel = RightSideSelectionViewModel.DataModelViewModel.GetChildByPath(
|
||||||
listDataModelGuid.Value, DataModelConditionListPredicate.RightPropertyPath
|
listDataModelGuid.Value, DataModelConditionListPredicate.RightPath?.Path
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else if (SelectedOperator.SupportsRightSide)
|
||||||
{
|
{
|
||||||
DisposeRightSideDynamic();
|
DisposeRightSideDynamic();
|
||||||
if (RightSideInputViewModel == null)
|
if (RightSideInputViewModel == null)
|
||||||
@ -205,16 +195,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
public void ApplyRightSideDynamic()
|
public void ApplyRightSideDynamic()
|
||||||
{
|
{
|
||||||
if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic)
|
if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic)
|
||||||
{
|
|
||||||
DataModelConditionListPredicate.UpdateRightSideDynamic(
|
DataModelConditionListPredicate.UpdateRightSideDynamic(
|
||||||
RightSideSelectionViewModel.SelectedPropertyViewModel.DataModel,
|
RightSideSelectionViewModel.SelectedPropertyViewModel.DataModel,
|
||||||
RightSideSelectionViewModel.SelectedPropertyViewModel.Path
|
RightSideSelectionViewModel.SelectedPropertyViewModel.Path
|
||||||
);
|
);
|
||||||
}
|
|
||||||
else if (DataModelConditionListPredicate.PredicateType == ListRightSideType.DynamicList)
|
else if (DataModelConditionListPredicate.PredicateType == ListRightSideType.DynamicList)
|
||||||
{
|
|
||||||
DataModelConditionListPredicate.UpdateRightSideDynamic(RightSideSelectionViewModel.SelectedPropertyViewModel.Path);
|
DataModelConditionListPredicate.UpdateRightSideDynamic(RightSideSelectionViewModel.SelectedPropertyViewModel.Path);
|
||||||
}
|
|
||||||
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
Update();
|
Update();
|
||||||
@ -238,10 +224,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
|
|
||||||
private DataModelVisualizationViewModel GetListDataModel()
|
private DataModelVisualizationViewModel GetListDataModel()
|
||||||
{
|
{
|
||||||
DataModelPropertiesViewModel dataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
if (DataModelConditionListPredicate.DataModelConditionList.ListPath?.DataModelGuid == null)
|
||||||
if (DataModelConditionListPredicate.DataModelConditionList.ListPath.DataModelGuid == null)
|
throw new ArtemisUIException("Failed to retrieve the list data model VM for this list predicate because it has no list path");
|
||||||
return null;
|
|
||||||
|
|
||||||
|
DataModelPropertiesViewModel dataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
||||||
DataModelListViewModel listDataModel = (DataModelListViewModel) dataModel.GetChildByPath(
|
DataModelListViewModel listDataModel = (DataModelListViewModel) dataModel.GetChildByPath(
|
||||||
DataModelConditionListPredicate.DataModelConditionList.ListPath.DataModelGuid.Value,
|
DataModelConditionListPredicate.DataModelConditionList.ListPath.DataModelGuid.Value,
|
||||||
DataModelConditionListPredicate.DataModelConditionList.ListPath.Path
|
DataModelConditionListPredicate.DataModelConditionList.ListPath.Path
|
||||||
@ -293,5 +279,17 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
RightSideSelectionViewModel = null;
|
RightSideSelectionViewModel = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_isPrimitiveList)
|
||||||
|
{
|
||||||
|
LeftSideSelectionViewModel.PropertySelected -= LeftSideOnPropertySelected;
|
||||||
|
LeftSideSelectionViewModel.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
DisposeRightSideDynamic();
|
||||||
|
DisposeRightSideStatic();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataModelConditionList.ListPath.Target, DataModelConditionList.ListPath.Path);
|
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataModelConditionList.ListPath?.Target, DataModelConditionList.ListPath?.Path);
|
||||||
NotifyOfPropertyChange(nameof(SelectedListOperator));
|
NotifyOfPropertyChange(nameof(SelectedListOperator));
|
||||||
|
|
||||||
// Remove VMs of effects no longer applied on the layer
|
// Remove VMs of effects no longer applied on the layer
|
||||||
|
|||||||
@ -118,25 +118,24 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
{
|
{
|
||||||
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
|
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
|
||||||
LeftSideSelectionViewModel.PopulateSelectedPropertyViewModel(
|
LeftSideSelectionViewModel.PopulateSelectedPropertyViewModel(
|
||||||
DataModelConditionPredicate.LeftPath.Target as DataModel,
|
DataModelConditionPredicate.LeftPath?.Target,
|
||||||
DataModelConditionPredicate.LeftPath.Path
|
DataModelConditionPredicate.LeftPath?.Path
|
||||||
);
|
);
|
||||||
Type leftSideType = LeftSideSelectionViewModel.SelectedPropertyViewModel?.DataModelPath?.GetPropertyType();
|
Type leftSideType = LeftSideSelectionViewModel.SelectedPropertyViewModel?.DataModelPath?.GetPropertyType();
|
||||||
|
|
||||||
// Get the supported operators
|
// Get the supported operators
|
||||||
Operators.Clear();
|
Operators.Clear();
|
||||||
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType ?? typeof(object)));
|
||||||
if (DataModelConditionPredicate.Operator == null)
|
if (DataModelConditionPredicate.Operator == null)
|
||||||
DataModelConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
DataModelConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType ?? typeof(object))));
|
||||||
SelectedOperator = DataModelConditionPredicate.Operator;
|
SelectedOperator = DataModelConditionPredicate.Operator;
|
||||||
if (!SelectedOperator.SupportsRightSide)
|
if (SelectedOperator == null || !SelectedOperator.SupportsRightSide)
|
||||||
{
|
{
|
||||||
DisposeRightSideStatic();
|
DisposeRightSideStatic();
|
||||||
DisposeRightSideDynamic();
|
DisposeRightSideDynamic();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the right side has the proper VM
|
// Ensure the right side has the proper VM
|
||||||
Type targetType = LeftSideSelectionViewModel?.SelectedPropertyViewModel?.DataModelPath?.GetPropertyType();
|
|
||||||
if (DataModelConditionPredicate.PredicateType == ProfileRightSideType.Dynamic && SelectedOperator.SupportsRightSide)
|
if (DataModelConditionPredicate.PredicateType == ProfileRightSideType.Dynamic && SelectedOperator.SupportsRightSide)
|
||||||
{
|
{
|
||||||
DisposeRightSideStatic();
|
DisposeRightSideStatic();
|
||||||
@ -148,24 +147,24 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
}
|
}
|
||||||
|
|
||||||
RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
|
RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
|
||||||
DataModelConditionPredicate.RightPath.Target as DataModel,
|
DataModelConditionPredicate.RightPath?.Target,
|
||||||
DataModelConditionPredicate.RightPath.Path
|
DataModelConditionPredicate.RightPath?.Path
|
||||||
);
|
);
|
||||||
RightSideSelectionViewModel.FilterTypes = new[] {targetType};
|
RightSideSelectionViewModel.FilterTypes = new[] {leftSideType};
|
||||||
}
|
}
|
||||||
else if (SelectedOperator.SupportsRightSide)
|
else if (SelectedOperator.SupportsRightSide)
|
||||||
{
|
{
|
||||||
DisposeRightSideDynamic();
|
DisposeRightSideDynamic();
|
||||||
if (RightSideInputViewModel == null)
|
if (RightSideInputViewModel == null)
|
||||||
{
|
{
|
||||||
RightSideInputViewModel = _dataModelUIService.GetStaticInputViewModel(targetType);
|
RightSideInputViewModel = _dataModelUIService.GetStaticInputViewModel(leftSideType);
|
||||||
RightSideInputViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
|
RightSideInputViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
|
||||||
RightSideInputViewModel.ValueUpdated += RightSideOnValueEntered;
|
RightSideInputViewModel.ValueUpdated += RightSideOnValueEntered;
|
||||||
}
|
}
|
||||||
|
|
||||||
RightSideInputViewModel.Value = DataModelConditionPredicate.RightStaticValue;
|
RightSideInputViewModel.Value = DataModelConditionPredicate.RightStaticValue;
|
||||||
if (RightSideInputViewModel.TargetType != targetType)
|
if (RightSideInputViewModel.TargetType != leftSideType)
|
||||||
RightSideInputViewModel.UpdateTargetType(targetType);
|
RightSideInputViewModel.UpdateTargetType(leftSideType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +212,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
|||||||
ApplyLeftSide();
|
ApplyLeftSide();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RightSideOnPropertySelected(object? sender, DataModelInputDynamicEventArgs e)
|
private void RightSideOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
|
||||||
{
|
{
|
||||||
ApplyRightSideDynamic();
|
ApplyRightSideDynamic();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -207,6 +207,7 @@
|
|||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FElsewhere/@EntryIndexedValue">ERROR</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FElsewhere/@EntryIndexedValue">ERROR</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FSimpleTypes/@EntryIndexedValue">ERROR</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">ERROR</s:String>
|
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=SuggestVarOrType_005FBuiltInTypes/@EntryIndexedValue">ERROR</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user