Conditions - Big refactor to prepare for conditional databindings

Conditions - Improved list-condition functionality
This commit is contained in:
SpoinkyNL committed 2020-09-20 21:34:27 +02:00
1 parent a646ff95ed
commit 8aba0a55ec
55 files changed
+1382 -1608

No files matched your search

@@ -62,7 +62,7 @@ namespace Artemis.Core
internal abstract bool EvaluateObject(object target);
internal abstract void Save();
internal abstract DisplayConditionPartEntity GetEntity();
internal abstract DataModelConditionPartEntity GetEntity();
#region IDisposable
@@ -20,7 +20,7 @@ namespace Artemis.Core
public DataModelConditionGroup(DataModelConditionPart parent)
{
Parent = parent;
Entity = new DisplayConditionGroupEntity();
Entity = new DataModelConditionGroupEntity();
}
/// <summary>
@@ -28,7 +28,7 @@ namespace Artemis.Core
/// </summary>
/// <param name="parent"></param>
/// <param name="entity"></param>
public DataModelConditionGroup(DataModelConditionPart parent, DisplayConditionGroupEntity entity)
public DataModelConditionGroup(DataModelConditionPart parent, DataModelConditionGroupEntity entity)
{
Parent = parent;
Entity = entity;
@@ -36,13 +36,13 @@ namespace Artemis.Core
foreach (var childEntity in Entity.Children)
{
if (childEntity is DisplayConditionGroupEntity groupEntity)
if (childEntity is DataModelConditionGroupEntity groupEntity)
AddChild(new DataModelConditionGroup(this, groupEntity));
else if (childEntity is DisplayConditionListEntity listEntity)
else if (childEntity is DataModelConditionListEntity listEntity)
AddChild(new DataModelConditionList(this, listEntity));
else if (childEntity is DisplayConditionPredicateEntity predicateEntity)
else if (childEntity is DataModelConditionPredicateEntity predicateEntity)
AddChild(new DataModelConditionPredicate(this, predicateEntity));
else if (childEntity is DisplayConditionListPredicateEntity listPredicateEntity)
else if (childEntity is DataModelConditionListPredicateEntity listPredicateEntity)
AddChild(new DataModelConditionListPredicate(this, listPredicateEntity));
}
}
@@ -52,13 +52,13 @@ namespace Artemis.Core
/// </summary>
public BooleanOperator BooleanOperator { get; set; }
internal DisplayConditionGroupEntity Entity { get; set; }
internal DataModelConditionGroupEntity Entity { get; set; }
/// <inheritdoc />
public override bool Evaluate()
{
if (_disposed)
throw new ObjectDisposedException("DisplayConditionGroup");
throw new ObjectDisposedException("DataModelConditionGroup");
// Empty groups are always true
if (Children.Count == 0)
@@ -100,7 +100,7 @@ namespace Artemis.Core
internal override bool EvaluateObject(object target)
{
if (_disposed)
throw new ObjectDisposedException("DisplayConditionGroup");
throw new ObjectDisposedException("DataModelConditionGroup");
// Empty groups are always true
if (Children.Count == 0)
@@ -129,7 +129,7 @@ namespace Artemis.Core
child.Save();
}
internal override DisplayConditionPartEntity GetEntity()
internal override DataModelConditionPartEntity GetEntity()
{
return Entity;
}
@@ -22,12 +22,12 @@ namespace Artemis.Core
public DataModelConditionList(DataModelConditionPart parent)
{
Parent = parent;
Entity = new DisplayConditionListEntity();
Entity = new DataModelConditionListEntity();
Initialize();
}
internal DataModelConditionList(DataModelConditionPart parent, DisplayConditionListEntity entity)
internal DataModelConditionList(DataModelConditionPart parent, DataModelConditionListEntity entity)
{
Parent = parent;
Entity = entity;
@@ -36,7 +36,7 @@ namespace Artemis.Core
Initialize();
}
internal DisplayConditionListEntity Entity { get; set; }
internal DataModelConditionListEntity Entity { get; set; }
/// <summary>
/// Gets or sets the list operator
@@ -62,7 +62,7 @@ namespace Artemis.Core
public override bool Evaluate()
{
if (_disposed)
throw new ObjectDisposedException("DisplayConditionList");
throw new ObjectDisposedException("DataModelConditionList");
if (CompiledListAccessor == null)
return false;
@@ -78,7 +78,7 @@ namespace Artemis.Core
public void UpdateList(DataModel dataModel, string path)
{
if (_disposed)
throw new ObjectDisposedException("DisplayConditionList");
throw new ObjectDisposedException("DataModelConditionList");
if (dataModel != null && path == null)
throw new ArtemisCoreException("If a data model is provided, a path is also required");
@@ -129,7 +129,7 @@ namespace Artemis.Core
internal override bool EvaluateObject(object target)
{
if (_disposed)
throw new ObjectDisposedException("DisplayConditionList");
throw new ObjectDisposedException("DataModelConditionList");
if (!Children.Any())
return false;
@@ -166,7 +166,7 @@ namespace Artemis.Core
child.Save();
}
internal override DisplayConditionPartEntity GetEntity()
internal override DataModelConditionPartEntity GetEntity()
{
return Entity;
}
@@ -189,7 +189,7 @@ namespace Artemis.Core
CreateExpression();
// There should only be one child and it should be a group
if (Entity.Children.SingleOrDefault() is DisplayConditionGroupEntity rootGroup)
if (Entity.Children.SingleOrDefault() is DataModelConditionGroupEntity rootGroup)
AddChild(new DataModelConditionGroup(this, rootGroup));
else
{
@@ -201,12 +201,14 @@ namespace Artemis.Core
private void CreateExpression()
{
if (_disposed)
throw new ObjectDisposedException("DisplayConditionList");
throw new ObjectDisposedException("DataModelConditionList");
var parameter = Expression.Parameter(typeof(object), "listDataModel");
var accessor = ListPropertyPath.Split('.').Aggregate<string, Expression>(
Expression.Convert(parameter, ListDataModel.GetType()),
(expression, s) => Expression.Convert(Expression.Property(expression, s), typeof(IList)));
Expression.Property
);
accessor = Expression.Convert(accessor, typeof(IList));
var lambda = Expression.Lambda<Func<object, IList>>(accessor, parameter);
CompiledListAccessor = lambda.Compile();
@@ -18,32 +18,32 @@ namespace Artemis.Core
/// </summary>
/// <param name="parent"></param>
/// <param name="predicateType"></param>
public DataModelConditionListPredicate(DataModelConditionPart parent, ProfileRightSideType predicateType)
public DataModelConditionListPredicate(DataModelConditionPart parent, ListRightSideType predicateType)
{
Parent = parent;
PredicateType = predicateType;
Entity = new DisplayConditionListPredicateEntity();
Entity = new DataModelConditionListPredicateEntity();
ApplyParentList();
Initialize();
}
internal DataModelConditionListPredicate(DataModelConditionPart parent, DisplayConditionListPredicateEntity entity)
internal DataModelConditionListPredicate(DataModelConditionPart parent, DataModelConditionListPredicateEntity entity)
{
Parent = parent;
Entity = entity;
PredicateType = (ProfileRightSideType) entity.PredicateType;
PredicateType = (ListRightSideType) entity.PredicateType;
ApplyParentList();
Initialize();
}
internal DisplayConditionListPredicateEntity Entity { get; set; }
internal DataModelConditionListPredicateEntity Entity { get; set; }
/// <summary>
/// Gets or sets the predicate type
/// </summary>
public ProfileRightSideType PredicateType { get; set; }
public ListRightSideType PredicateType { get; set; }
/// <summary>
/// Gets the operator
@@ -55,6 +55,11 @@ namespace Artemis.Core
/// </summary>
public Type ListType { get; private set; }
/// <summary>
/// Gets whether the list contains primitives
/// </summary>
public bool IsPrimitiveList { get; private set; }
/// <summary>
/// Gets the currently used instance of the list data model
/// </summary>
@@ -70,6 +75,12 @@ namespace Artemis.Core
/// </summary>
public string LeftPropertyPath { get; private set; }
/// <summary>
/// Gets the currently used instance of the right side data model
/// <para>Note: This is null when using a path inside the list</para>
/// </summary>
public DataModel RightDataModel { get; set; }
/// <summary>
/// Gets the path of the right property in the <see cref="ListType" />
/// </summary>
@@ -77,21 +88,28 @@ namespace Artemis.Core
/// <summary>
/// Gets the right static value, only used it <see cref="PredicateType" /> is
/// <see cref="ProfileRightSideType.Static" />
/// <see cref="ListRightSideType.Static" />
/// </summary>
public object RightStaticValue { get; private set; }
/// <summary>
/// Gets the compiled function that evaluates this predicate
/// Gets the compiled expression that evaluates this predicate
/// </summary>
public Func<object, bool> CompiledListPredicate { get; private set; }
/// <summary>
/// Gets the compiled expression that evaluates this predicate on an external right-side data model
/// </summary>
public Func<object, DataModel, bool> CompiledExternalListPredicate { get; set; }
/// <summary>
/// Updates the left side of the predicate
/// </summary>
/// <param name="path">The path pointing to the left side value inside the list</param>
public void UpdateLeftSide(string path)
{
if (IsPrimitiveList)
throw new ArtemisCoreException("Cannot apply a left side to a predicate inside a primitive list");
if (!ListContainsInnerPath(path))
throw new ArtemisCoreException($"List type {ListType.Name} does not contain path {path}");
@@ -103,7 +121,8 @@ namespace Artemis.Core
}
/// <summary>
/// Updates the right side of the predicate, makes the predicate dynamic and re-compiles the expression
/// Updates the right side of the predicate using a path to a value inside the list item, makes the predicate dynamic
/// and re-compiles the expression
/// </summary>
/// <param name="path">The path pointing to the right side value inside the list</param>
public void UpdateRightSideDynamic(string path)
@@ -111,7 +130,33 @@ namespace Artemis.Core
if (!ListContainsInnerPath(path))
throw new ArtemisCoreException($"List type {ListType.Name} does not contain path {path}");
PredicateType = ProfileRightSideType.Dynamic;
PredicateType = ListRightSideType.Dynamic;
RightPropertyPath = path;
CreateExpression();
}
/// <summary>
/// Updates the right side of the predicate using path to a value in a data model, makes the predicate dynamic and
/// re-compiles the expression
/// </summary>
/// <param name="dataModel"></param>
/// <param name="path">The path pointing to the right side value inside the list</param>
public void UpdateRightSideDynamic(DataModel dataModel, string path)
{
if (dataModel != null && path == null)
throw new ArtemisCoreException("If a data model is provided, a path is also required");
if (dataModel == null && path != null)
throw new ArtemisCoreException("If path is provided, a data model is also required");
if (dataModel != null)
{
if (!dataModel.ContainsPath(path))
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a property at path '{path}'");
}
PredicateType = ListRightSideType.DynamicExternal;
RightDataModel = dataModel;
RightPropertyPath = path;
CreateExpression();
@@ -123,7 +168,7 @@ namespace Artemis.Core
/// <param name="staticValue">The right side value to use</param>
public void UpdateRightSideStatic(object staticValue)
{
PredicateType = ProfileRightSideType.Static;
PredicateType = ListRightSideType.Static;
RightPropertyPath = null;
SetStaticValue(staticValue);
@@ -163,11 +208,36 @@ namespace Artemis.Core
return false;
}
/// <summary>
/// Determines whether the provided path is contained inside the list
/// </summary>
/// <param name="path">The path to evaluate</param>
public bool ListContainsInnerPath(string path)
{
if (ListType == null)
return false;
var parts = path.Split('.');
var current = ListType;
foreach (var part in parts)
{
var property = current.GetProperty(part);
current = property?.PropertyType;
if (property == null)
return false;
}
return true;
}
#region IDisposable
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
@@ -205,9 +275,14 @@ namespace Artemis.Core
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{path}'");
ListType = listType;
IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string);
}
else
{
ListType = null;
IsPrimitiveList = true;
}
ListDataModel = dataModel;
ListPropertyPath = path;
@@ -220,6 +295,7 @@ namespace Artemis.Core
CreateExpression();
}
/// <summary>
/// Evaluates the condition part on the given target
/// </summary>
@@ -229,26 +305,14 @@ namespace Artemis.Core
/// </param>
internal override bool EvaluateObject(object target)
{
return CompiledListPredicate != null && CompiledListPredicate(target);
}
if (PredicateType == ListRightSideType.Static && CompiledListPredicate != null)
return CompiledListPredicate(target);
if (PredicateType == ListRightSideType.Dynamic && CompiledListPredicate != null)
return CompiledListPredicate(target);
if (PredicateType == ListRightSideType.DynamicExternal && CompiledExternalListPredicate != null)
return CompiledExternalListPredicate(target, RightDataModel);
internal bool ListContainsInnerPath(string path)
{
if (ListType == null)
return false;
var parts = path.Split('.');
var current = ListType;
foreach (var part in parts)
{
var property = current.GetProperty(part);
current = property?.PropertyType;
if (property == null)
return false;
}
return true;
return false;
}
internal Type GetTypeAtInnerPath(string path)
@@ -280,6 +344,8 @@ namespace Artemis.Core
}
Entity.LeftPropertyPath = LeftPropertyPath;
Entity.RightDataModelGuid = RightDataModel?.PluginInfo?.Guid;
Entity.RightPropertyPath = RightPropertyPath;
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
@@ -290,13 +356,15 @@ namespace Artemis.Core
}
}
internal override DisplayConditionPartEntity GetEntity()
internal override DataModelConditionPartEntity GetEntity()
{
return Entity;
}
private void Initialize()
{
DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
@@ -313,13 +381,20 @@ namespace Artemis.Core
}
// Right side dynamic
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPropertyPath != null)
if (PredicateType == ListRightSideType.Dynamic && Entity.RightPropertyPath != null)
{
if (ListContainsInnerPath(Entity.RightPropertyPath))
UpdateRightSideDynamic(Entity.RightPropertyPath);
}
// Right side dynamic using an external data model
else if (PredicateType == ListRightSideType.Dynamic && Entity.RightDataModelGuid != null && Entity.RightPropertyPath != null)
{
var dataModel = DataModelStore.Get(Entity.RightDataModelGuid.Value)?.DataModel;
if (dataModel != null && dataModel.ContainsPath(Entity.RightPropertyPath))
UpdateRightSideDynamic(dataModel, Entity.RightPropertyPath);
}
// Right side static
else if (PredicateType == ProfileRightSideType.Static && Entity.RightStaticValue != null)
else if (PredicateType == ListRightSideType.Static && Entity.RightStaticValue != null)
{
try
{
@@ -363,10 +438,12 @@ namespace Artemis.Core
return;
// If the operator does not support a right side, create a static expression because the right side will simply be null
if (PredicateType == ProfileRightSideType.Dynamic && Operator.SupportsRightSide)
if (PredicateType == ListRightSideType.Dynamic && Operator.SupportsRightSide)
CreateDynamicExpression();
CreateStaticExpression();
else if (PredicateType == ListRightSideType.DynamicExternal && Operator.SupportsRightSide)
CreateDynamicExternalExpression();
else
CreateStaticExpression();
}
private void ValidateOperator()
@@ -382,7 +459,7 @@ namespace Artemis.Core
private void ValidateRightSide()
{
var leftSideType = GetTypeAtInnerPath(LeftPropertyPath);
if (PredicateType == ProfileRightSideType.Dynamic)
if (PredicateType == ListRightSideType.Dynamic)
{
if (RightPropertyPath == null)
return;
@@ -391,6 +468,15 @@ namespace Artemis.Core
if (!leftSideType.IsCastableFrom(rightSideType))
UpdateRightSideDynamic(null);
}
else if (PredicateType == ListRightSideType.DynamicExternal)
{
if (RightDataModel == null)
return;
var rightSideType = RightDataModel.GetTypeAtPath(RightPropertyPath);
if (!leftSideType.IsCastableFrom(rightSideType))
UpdateRightSideDynamic(null, null);
}
else
{
if (RightStaticValue != null && leftSideType.IsCastableFrom(RightStaticValue.GetType()))
@@ -434,7 +520,7 @@ namespace Artemis.Core
var rightSideAccessor = CreateListAccessor(RightPropertyPath, leftSideParameter);
// A conversion may be required if the types differ
// This can cause issues if the DisplayConditionOperator wasn't accurate in it's supported types but that is not a concern here
// 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);
@@ -443,14 +529,34 @@ namespace Artemis.Core
CompiledListPredicate = lambda.Compile();
}
private void CreateStaticExpression()
private void CreateDynamicExternalExpression()
{
if (LeftPropertyPath == null || Operator == null)
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
var leftSideParameter = Expression.Parameter(typeof(object), "listItem");
var leftSideAccessor = CreateListAccessor(LeftPropertyPath, leftSideParameter);
var rightSideAccessor = CreateAccessor(RightDataModel, RightPropertyPath, "right", out var 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);
var conditionExpression = Operator.CreateExpression(leftSideAccessor, rightSideAccessor);
var lambda = Expression.Lambda<Func<object, DataModel, bool>>(conditionExpression, leftSideParameter, rightSideParameter);
CompiledExternalListPredicate = lambda.Compile();
}
private void CreateStaticExpression()
{
if (!IsPrimitiveList && LeftPropertyPath == null || Operator == null)
return;
// List accessors share the same parameter because a list always contains one item per entry
var leftSideParameter = Expression.Parameter(typeof(object), "listItem");
var leftSideAccessor = IsPrimitiveList ? Expression.Convert(leftSideParameter, ListType) : CreateListAccessor(LeftPropertyPath, leftSideParameter);
// If the left side is a value type but the input is empty, this isn't a valid expression
if (leftSideAccessor.Type.IsValueType && RightStaticValue == null)
@@ -458,7 +564,7 @@ namespace Artemis.Core
// If the right side value is null, the constant type cannot be inferred and must be provided manually
var rightSideConstant = RightStaticValue != null
? Expression.Constant(RightStaticValue)
? Expression.Constant(Convert.ChangeType(RightStaticValue, leftSideAccessor.Type))
: Expression.Constant(null, leftSideAccessor.Type);
var conditionExpression = Operator.CreateExpression(leftSideAccessor, rightSideConstant);
@@ -474,8 +580,46 @@ namespace Artemis.Core
);
}
private Expression CreateAccessor(DataModel dataModel, string path, string parameterName, out ParameterExpression parameter)
{
var listType = dataModel.GetListTypeInPath(path);
if (listType != null)
throw new ArtemisCoreException($"Cannot create a regular accessor at path {path} because the path contains a list");
parameter = Expression.Parameter(typeof(object), parameterName + "DataModel");
return path.Split('.').Aggregate<string, Expression>(
Expression.Convert(parameter, dataModel.GetType()), // Cast to the appropriate type
Expression.Property
);
}
#region Event handlers
private void DataModelStoreOnDataModelAdded(object sender, DataModelStoreEvent e)
{
var dataModel = e.Registration.DataModel;
if (dataModel.PluginInfo.Guid == Entity.ListDataModelGuid && dataModel.ContainsPath(Entity.ListPropertyPath))
UpdateList(dataModel, Entity.LeftPropertyPath);
if (dataModel.PluginInfo.Guid == Entity.RightDataModelGuid && dataModel.ContainsPath(Entity.RightPropertyPath))
UpdateRightSideDynamic(dataModel, Entity.RightPropertyPath);
}
private void DataModelStoreOnDataModelRemoved(object sender, DataModelStoreEvent e)
{
if (ListDataModel == e.Registration.DataModel)
{
CompiledListPredicate = null;
CompiledExternalListPredicate = null;
ListDataModel = null;
}
if (RightDataModel == e.Registration.DataModel)
{
CompiledExternalListPredicate = null;
RightDataModel = null;
}
}
private void ConditionOperatorStoreOnConditionOperatorAdded(object sender, ConditionOperatorStoreEvent e)
{
var conditionOperator = e.Registration.ConditionOperator;
@@ -493,4 +637,25 @@ namespace Artemis.Core
#endregion
}
/// <summary>
/// An enum defining the right side type of a profile entity
/// </summary>
public enum ListRightSideType
{
/// <summary>
/// A static right side value
/// </summary>
Static,
/// <summary>
/// A dynamic right side value based on a path in the list
/// </summary>
Dynamic,
/// <summary>
/// A dynamic right side value based on a path in a data model
/// </summary>
DynamicExternal
}
}
@@ -23,12 +23,12 @@ namespace Artemis.Core
{
Parent = parent;
PredicateType = predicateType;
Entity = new DisplayConditionPredicateEntity();
Entity = new DataModelConditionPredicateEntity();
Initialize();
}
internal DataModelConditionPredicate(DataModelConditionPart parent, DisplayConditionPredicateEntity entity)
internal DataModelConditionPredicate(DataModelConditionPart parent, DataModelConditionPredicateEntity entity)
{
Parent = parent;
Entity = entity;
@@ -83,7 +83,7 @@ namespace Artemis.Core
/// </summary>
public Func<DataModel, bool> CompiledStaticPredicate { get; private set; }
internal DisplayConditionPredicateEntity Entity { get; set; }
internal DataModelConditionPredicateEntity Entity { get; set; }
/// <summary>
/// Updates the left side of the predicate
@@ -309,7 +309,7 @@ namespace Artemis.Core
}
}
internal override DisplayConditionPartEntity GetEntity()
internal override DataModelConditionPartEntity GetEntity()
{
return Entity;
}
@@ -369,7 +369,7 @@ namespace Artemis.Core
var rightSideAccessor = CreateAccessor(RightDataModel, RightPropertyPath, "right", out var rightSideParameter);
// A conversion may be required if the types differ
// This can cause issues if the DisplayConditionOperator wasn't accurate in it's supported types but that is not a concern here
// 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);
@@ -391,7 +391,7 @@ namespace Artemis.Core
// If the right side value is null, the constant type cannot be inferred and must be provided manually
var rightSideConstant = RightStaticValue != null
? Expression.Constant(RightStaticValue)
? Expression.Constant(Convert.ChangeType(RightStaticValue, leftSideAccessor.Type))
: Expression.Constant(null, leftSideAccessor.Type);
var conditionExpression = Operator.CreateExpression(leftSideAccessor, rightSideConstant);
@@ -72,6 +72,9 @@ namespace Artemis.Core
{
_disposed = true;
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
foreach (var dataBindingModifier in Modifiers)
dataBindingModifier.Dispose();
}
@@ -153,8 +156,7 @@ namespace Artemis.Core
{
return SourceDataModel?.GetTypeAtPath(SourcePropertyPath);
}
/// <summary>
/// Updates the source of the data binding and re-compiles the expression
/// </summary>
@@ -49,8 +49,8 @@ namespace Artemis.Core
DisplayContinuously = RenderElementEntity.DisplayContinuously;
AlwaysFinishTimeline = RenderElementEntity.AlwaysFinishTimeline;
DataModelConditionGroup = RenderElementEntity.RootDisplayCondition != null
? new DataModelConditionGroup(null, RenderElementEntity.RootDisplayCondition)
DisplayCondition = RenderElementEntity.DisplayCondition != null
? new DataModelConditionGroup(null, RenderElementEntity.DisplayCondition)
: new DataModelConditionGroup(null);
ActivateEffects();
@@ -82,8 +82,8 @@ namespace Artemis.Core
}
// Conditions
RenderElementEntity.RootDisplayCondition = DataModelConditionGroup?.Entity;
DataModelConditionGroup?.Save();
RenderElementEntity.DisplayCondition = DisplayCondition?.Entity;
DisplayCondition?.Save();
}
#region Properties
@@ -392,22 +392,22 @@ namespace Artemis.Core
private set => SetAndNotify(ref _displayConditionMet, value);
}
private DataModelConditionGroup _dataModelConditionGroup;
private DataModelConditionGroup _displayCondition;
private TimeSpan _timelinePosition;
private bool _displayConditionMet;
/// <summary>
/// Gets or sets the root display condition group
/// </summary>
public DataModelConditionGroup DataModelConditionGroup
public DataModelConditionGroup DisplayCondition
{
get => _dataModelConditionGroup;
set => SetAndNotify(ref _dataModelConditionGroup, value);
get => _displayCondition;
set => SetAndNotify(ref _displayCondition, value);
}
public void UpdateDisplayCondition()
{
var conditionMet = DataModelConditionGroup == null || DataModelConditionGroup.Evaluate();
var conditionMet = DisplayCondition == null || DisplayCondition.Evaluate();
if (conditionMet && !DisplayConditionMet)
TimelinePosition = TimeSpan.Zero;