mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Conditions - Big refactor to prepare for conditional databindings
Conditions - Improved list-condition functionality
This commit is contained in:
parent
a646ff95ed
commit
8aba0a55ec
@ -62,7 +62,7 @@ namespace Artemis.Core
|
|||||||
internal abstract bool EvaluateObject(object target);
|
internal abstract bool EvaluateObject(object target);
|
||||||
|
|
||||||
internal abstract void Save();
|
internal abstract void Save();
|
||||||
internal abstract DisplayConditionPartEntity GetEntity();
|
internal abstract DataModelConditionPartEntity GetEntity();
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ namespace Artemis.Core
|
|||||||
public DataModelConditionGroup(DataModelConditionPart parent)
|
public DataModelConditionGroup(DataModelConditionPart parent)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Entity = new DisplayConditionGroupEntity();
|
Entity = new DataModelConditionGroupEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -28,7 +28,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parent"></param>
|
/// <param name="parent"></param>
|
||||||
/// <param name="entity"></param>
|
/// <param name="entity"></param>
|
||||||
public DataModelConditionGroup(DataModelConditionPart parent, DisplayConditionGroupEntity entity)
|
public DataModelConditionGroup(DataModelConditionPart parent, DataModelConditionGroupEntity entity)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
@ -36,13 +36,13 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
foreach (var childEntity in Entity.Children)
|
foreach (var childEntity in Entity.Children)
|
||||||
{
|
{
|
||||||
if (childEntity is DisplayConditionGroupEntity groupEntity)
|
if (childEntity is DataModelConditionGroupEntity groupEntity)
|
||||||
AddChild(new DataModelConditionGroup(this, groupEntity));
|
AddChild(new DataModelConditionGroup(this, groupEntity));
|
||||||
else if (childEntity is DisplayConditionListEntity listEntity)
|
else if (childEntity is DataModelConditionListEntity listEntity)
|
||||||
AddChild(new DataModelConditionList(this, listEntity));
|
AddChild(new DataModelConditionList(this, listEntity));
|
||||||
else if (childEntity is DisplayConditionPredicateEntity predicateEntity)
|
else if (childEntity is DataModelConditionPredicateEntity predicateEntity)
|
||||||
AddChild(new DataModelConditionPredicate(this, predicateEntity));
|
AddChild(new DataModelConditionPredicate(this, predicateEntity));
|
||||||
else if (childEntity is DisplayConditionListPredicateEntity listPredicateEntity)
|
else if (childEntity is DataModelConditionListPredicateEntity listPredicateEntity)
|
||||||
AddChild(new DataModelConditionListPredicate(this, listPredicateEntity));
|
AddChild(new DataModelConditionListPredicate(this, listPredicateEntity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,13 +52,13 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public BooleanOperator BooleanOperator { get; set; }
|
public BooleanOperator BooleanOperator { get; set; }
|
||||||
|
|
||||||
internal DisplayConditionGroupEntity Entity { get; set; }
|
internal DataModelConditionGroupEntity Entity { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Evaluate()
|
public override bool Evaluate()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DisplayConditionGroup");
|
throw new ObjectDisposedException("DataModelConditionGroup");
|
||||||
|
|
||||||
// Empty groups are always true
|
// Empty groups are always true
|
||||||
if (Children.Count == 0)
|
if (Children.Count == 0)
|
||||||
@ -100,7 +100,7 @@ namespace Artemis.Core
|
|||||||
internal override bool EvaluateObject(object target)
|
internal override bool EvaluateObject(object target)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DisplayConditionGroup");
|
throw new ObjectDisposedException("DataModelConditionGroup");
|
||||||
|
|
||||||
// Empty groups are always true
|
// Empty groups are always true
|
||||||
if (Children.Count == 0)
|
if (Children.Count == 0)
|
||||||
@ -129,7 +129,7 @@ namespace Artemis.Core
|
|||||||
child.Save();
|
child.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DisplayConditionPartEntity GetEntity()
|
internal override DataModelConditionPartEntity GetEntity()
|
||||||
{
|
{
|
||||||
return Entity;
|
return Entity;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,12 +22,12 @@ namespace Artemis.Core
|
|||||||
public DataModelConditionList(DataModelConditionPart parent)
|
public DataModelConditionList(DataModelConditionPart parent)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Entity = new DisplayConditionListEntity();
|
Entity = new DataModelConditionListEntity();
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DataModelConditionList(DataModelConditionPart parent, DisplayConditionListEntity entity)
|
internal DataModelConditionList(DataModelConditionPart parent, DataModelConditionListEntity entity)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
@ -36,7 +36,7 @@ namespace Artemis.Core
|
|||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DisplayConditionListEntity Entity { get; set; }
|
internal DataModelConditionListEntity Entity { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the list operator
|
/// Gets or sets the list operator
|
||||||
@ -62,7 +62,7 @@ namespace Artemis.Core
|
|||||||
public override bool Evaluate()
|
public override bool Evaluate()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DisplayConditionList");
|
throw new ObjectDisposedException("DataModelConditionList");
|
||||||
|
|
||||||
if (CompiledListAccessor == null)
|
if (CompiledListAccessor == null)
|
||||||
return false;
|
return false;
|
||||||
@ -78,7 +78,7 @@ namespace Artemis.Core
|
|||||||
public void UpdateList(DataModel dataModel, string path)
|
public void UpdateList(DataModel dataModel, string path)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DisplayConditionList");
|
throw new ObjectDisposedException("DataModelConditionList");
|
||||||
|
|
||||||
if (dataModel != null && path == null)
|
if (dataModel != null && path == null)
|
||||||
throw new ArtemisCoreException("If a data model is provided, a path is also required");
|
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)
|
internal override bool EvaluateObject(object target)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DisplayConditionList");
|
throw new ObjectDisposedException("DataModelConditionList");
|
||||||
|
|
||||||
if (!Children.Any())
|
if (!Children.Any())
|
||||||
return false;
|
return false;
|
||||||
@ -166,7 +166,7 @@ namespace Artemis.Core
|
|||||||
child.Save();
|
child.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DisplayConditionPartEntity GetEntity()
|
internal override DataModelConditionPartEntity GetEntity()
|
||||||
{
|
{
|
||||||
return Entity;
|
return Entity;
|
||||||
}
|
}
|
||||||
@ -189,7 +189,7 @@ namespace Artemis.Core
|
|||||||
CreateExpression();
|
CreateExpression();
|
||||||
|
|
||||||
// There should only be one child and it should be a group
|
// 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));
|
AddChild(new DataModelConditionGroup(this, rootGroup));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -201,12 +201,14 @@ namespace Artemis.Core
|
|||||||
private void CreateExpression()
|
private void CreateExpression()
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
throw new ObjectDisposedException("DisplayConditionList");
|
throw new ObjectDisposedException("DataModelConditionList");
|
||||||
|
|
||||||
var parameter = Expression.Parameter(typeof(object), "listDataModel");
|
var parameter = Expression.Parameter(typeof(object), "listDataModel");
|
||||||
var accessor = ListPropertyPath.Split('.').Aggregate<string, Expression>(
|
var accessor = ListPropertyPath.Split('.').Aggregate<string, Expression>(
|
||||||
Expression.Convert(parameter, ListDataModel.GetType()),
|
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);
|
var lambda = Expression.Lambda<Func<object, IList>>(accessor, parameter);
|
||||||
CompiledListAccessor = lambda.Compile();
|
CompiledListAccessor = lambda.Compile();
|
||||||
|
|||||||
@ -18,32 +18,32 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parent"></param>
|
/// <param name="parent"></param>
|
||||||
/// <param name="predicateType"></param>
|
/// <param name="predicateType"></param>
|
||||||
public DataModelConditionListPredicate(DataModelConditionPart parent, ProfileRightSideType predicateType)
|
public DataModelConditionListPredicate(DataModelConditionPart parent, ListRightSideType predicateType)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
PredicateType = predicateType;
|
PredicateType = predicateType;
|
||||||
Entity = new DisplayConditionListPredicateEntity();
|
Entity = new DataModelConditionListPredicateEntity();
|
||||||
|
|
||||||
ApplyParentList();
|
ApplyParentList();
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DataModelConditionListPredicate(DataModelConditionPart parent, DisplayConditionListPredicateEntity entity)
|
internal DataModelConditionListPredicate(DataModelConditionPart parent, DataModelConditionListPredicateEntity entity)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
PredicateType = (ProfileRightSideType) entity.PredicateType;
|
PredicateType = (ListRightSideType) entity.PredicateType;
|
||||||
|
|
||||||
ApplyParentList();
|
ApplyParentList();
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DisplayConditionListPredicateEntity Entity { get; set; }
|
internal DataModelConditionListPredicateEntity Entity { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the predicate type
|
/// Gets or sets the predicate type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProfileRightSideType PredicateType { get; set; }
|
public ListRightSideType PredicateType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the operator
|
/// Gets the operator
|
||||||
@ -55,6 +55,11 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Type ListType { get; private set; }
|
public Type ListType { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets whether the list contains primitives
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPrimitiveList { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the currently used instance of the list data model
|
/// Gets the currently used instance of the list data model
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -70,6 +75,12 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string LeftPropertyPath { get; private set; }
|
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>
|
/// <summary>
|
||||||
/// Gets the path of the right property in the <see cref="ListType" />
|
/// Gets the path of the right property in the <see cref="ListType" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -77,21 +88,28 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the right static value, only used it <see cref="PredicateType" /> is
|
/// Gets the right static value, only used it <see cref="PredicateType" /> is
|
||||||
/// <see cref="ProfileRightSideType.Static" />
|
/// <see cref="ListRightSideType.Static" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object RightStaticValue { get; private set; }
|
public object RightStaticValue { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the compiled function that evaluates this predicate
|
/// Gets the compiled expression that evaluates this predicate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<object, bool> CompiledListPredicate { get; private set; }
|
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>
|
/// <summary>
|
||||||
/// Updates the left side of the predicate
|
/// Updates the left side of the predicate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path pointing to the left side value inside the list</param>
|
/// <param name="path">The path pointing to the left side value inside the list</param>
|
||||||
public void UpdateLeftSide(string path)
|
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))
|
if (!ListContainsInnerPath(path))
|
||||||
throw new ArtemisCoreException($"List type {ListType.Name} does not contain path {path}");
|
throw new ArtemisCoreException($"List type {ListType.Name} does not contain path {path}");
|
||||||
|
|
||||||
@ -103,7 +121,8 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
/// <param name="path">The path pointing to the right side value inside the list</param>
|
/// <param name="path">The path pointing to the right side value inside the list</param>
|
||||||
public void UpdateRightSideDynamic(string path)
|
public void UpdateRightSideDynamic(string path)
|
||||||
@ -111,7 +130,33 @@ namespace Artemis.Core
|
|||||||
if (!ListContainsInnerPath(path))
|
if (!ListContainsInnerPath(path))
|
||||||
throw new ArtemisCoreException($"List type {ListType.Name} does not contain path {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;
|
RightPropertyPath = path;
|
||||||
|
|
||||||
CreateExpression();
|
CreateExpression();
|
||||||
@ -123,7 +168,7 @@ namespace Artemis.Core
|
|||||||
/// <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 = ProfileRightSideType.Static;
|
PredicateType = ListRightSideType.Static;
|
||||||
RightPropertyPath = null;
|
RightPropertyPath = null;
|
||||||
|
|
||||||
SetStaticValue(staticValue);
|
SetStaticValue(staticValue);
|
||||||
@ -163,11 +208,36 @@ namespace Artemis.Core
|
|||||||
return false;
|
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
|
#region IDisposable
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
|
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
||||||
|
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
||||||
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
|
ConditionOperatorStore.ConditionOperatorAdded -= ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
ConditionOperatorStore.ConditionOperatorRemoved -= ConditionOperatorStoreOnConditionOperatorRemoved;
|
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}'");
|
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{path}'");
|
||||||
|
|
||||||
ListType = listType;
|
ListType = listType;
|
||||||
|
IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
ListType = null;
|
ListType = null;
|
||||||
|
IsPrimitiveList = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ListDataModel = dataModel;
|
ListDataModel = dataModel;
|
||||||
ListPropertyPath = path;
|
ListPropertyPath = path;
|
||||||
@ -220,6 +295,7 @@ namespace Artemis.Core
|
|||||||
CreateExpression();
|
CreateExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Evaluates the condition part on the given target
|
/// Evaluates the condition part on the given target
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -229,26 +305,14 @@ namespace Artemis.Core
|
|||||||
/// </param>
|
/// </param>
|
||||||
internal override bool EvaluateObject(object target)
|
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)
|
return false;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Type GetTypeAtInnerPath(string path)
|
internal Type GetTypeAtInnerPath(string path)
|
||||||
@ -280,6 +344,8 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity.LeftPropertyPath = LeftPropertyPath;
|
Entity.LeftPropertyPath = LeftPropertyPath;
|
||||||
|
|
||||||
|
Entity.RightDataModelGuid = RightDataModel?.PluginInfo?.Guid;
|
||||||
Entity.RightPropertyPath = RightPropertyPath;
|
Entity.RightPropertyPath = RightPropertyPath;
|
||||||
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
Entity.RightStaticValue = JsonConvert.SerializeObject(RightStaticValue);
|
||||||
|
|
||||||
@ -290,13 +356,15 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DisplayConditionPartEntity GetEntity()
|
internal override DataModelConditionPartEntity GetEntity()
|
||||||
{
|
{
|
||||||
return Entity;
|
return Entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
|
DataModelStore.DataModelAdded += DataModelStoreOnDataModelAdded;
|
||||||
|
DataModelStore.DataModelRemoved += DataModelStoreOnDataModelRemoved;
|
||||||
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
|
ConditionOperatorStore.ConditionOperatorAdded += ConditionOperatorStoreOnConditionOperatorAdded;
|
||||||
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
ConditionOperatorStore.ConditionOperatorRemoved += ConditionOperatorStoreOnConditionOperatorRemoved;
|
||||||
|
|
||||||
@ -313,13 +381,20 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Right side dynamic
|
// Right side dynamic
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPropertyPath != null)
|
if (PredicateType == ListRightSideType.Dynamic && Entity.RightPropertyPath != null)
|
||||||
{
|
{
|
||||||
if (ListContainsInnerPath(Entity.RightPropertyPath))
|
if (ListContainsInnerPath(Entity.RightPropertyPath))
|
||||||
UpdateRightSideDynamic(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
|
// Right side static
|
||||||
else if (PredicateType == ProfileRightSideType.Static && Entity.RightStaticValue != null)
|
else if (PredicateType == ListRightSideType.Static && Entity.RightStaticValue != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -363,10 +438,12 @@ namespace Artemis.Core
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// If the operator does not support a right side, create a static expression because the right side will simply be null
|
// 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();
|
CreateDynamicExpression();
|
||||||
|
else if (PredicateType == ListRightSideType.DynamicExternal && Operator.SupportsRightSide)
|
||||||
CreateStaticExpression();
|
CreateDynamicExternalExpression();
|
||||||
|
else
|
||||||
|
CreateStaticExpression();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateOperator()
|
private void ValidateOperator()
|
||||||
@ -382,7 +459,7 @@ namespace Artemis.Core
|
|||||||
private void ValidateRightSide()
|
private void ValidateRightSide()
|
||||||
{
|
{
|
||||||
var leftSideType = GetTypeAtInnerPath(LeftPropertyPath);
|
var leftSideType = GetTypeAtInnerPath(LeftPropertyPath);
|
||||||
if (PredicateType == ProfileRightSideType.Dynamic)
|
if (PredicateType == ListRightSideType.Dynamic)
|
||||||
{
|
{
|
||||||
if (RightPropertyPath == null)
|
if (RightPropertyPath == null)
|
||||||
return;
|
return;
|
||||||
@ -391,6 +468,15 @@ namespace Artemis.Core
|
|||||||
if (!leftSideType.IsCastableFrom(rightSideType))
|
if (!leftSideType.IsCastableFrom(rightSideType))
|
||||||
UpdateRightSideDynamic(null);
|
UpdateRightSideDynamic(null);
|
||||||
}
|
}
|
||||||
|
else if (PredicateType == ListRightSideType.DynamicExternal)
|
||||||
|
{
|
||||||
|
if (RightDataModel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var rightSideType = RightDataModel.GetTypeAtPath(RightPropertyPath);
|
||||||
|
if (!leftSideType.IsCastableFrom(rightSideType))
|
||||||
|
UpdateRightSideDynamic(null, null);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (RightStaticValue != null && leftSideType.IsCastableFrom(RightStaticValue.GetType()))
|
if (RightStaticValue != null && leftSideType.IsCastableFrom(RightStaticValue.GetType()))
|
||||||
@ -434,7 +520,7 @@ namespace Artemis.Core
|
|||||||
var rightSideAccessor = CreateListAccessor(RightPropertyPath, leftSideParameter);
|
var rightSideAccessor = CreateListAccessor(RightPropertyPath, leftSideParameter);
|
||||||
|
|
||||||
// A conversion may be required if the types differ
|
// 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)
|
if (rightSideAccessor.Type != leftSideAccessor.Type)
|
||||||
rightSideAccessor = Expression.Convert(rightSideAccessor, leftSideAccessor.Type);
|
rightSideAccessor = Expression.Convert(rightSideAccessor, leftSideAccessor.Type);
|
||||||
|
|
||||||
@ -443,14 +529,34 @@ namespace Artemis.Core
|
|||||||
CompiledListPredicate = lambda.Compile();
|
CompiledListPredicate = lambda.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateStaticExpression()
|
private void CreateDynamicExternalExpression()
|
||||||
{
|
{
|
||||||
if (LeftPropertyPath == null || Operator == null)
|
if (LeftPropertyPath == null || RightPropertyPath == null || RightDataModel == null || Operator == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// List accessors share the same parameter because a list always contains one item per entry
|
// List accessors share the same parameter because a list always contains one item per entry
|
||||||
var leftSideParameter = Expression.Parameter(typeof(object), "listItem");
|
var leftSideParameter = Expression.Parameter(typeof(object), "listItem");
|
||||||
var leftSideAccessor = CreateListAccessor(LeftPropertyPath, leftSideParameter);
|
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 the left side is a value type but the input is empty, this isn't a valid expression
|
||||||
if (leftSideAccessor.Type.IsValueType && RightStaticValue == null)
|
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
|
// If the right side value is null, the constant type cannot be inferred and must be provided manually
|
||||||
var rightSideConstant = RightStaticValue != null
|
var rightSideConstant = RightStaticValue != null
|
||||||
? Expression.Constant(RightStaticValue)
|
? Expression.Constant(Convert.ChangeType(RightStaticValue, leftSideAccessor.Type))
|
||||||
: Expression.Constant(null, leftSideAccessor.Type);
|
: Expression.Constant(null, leftSideAccessor.Type);
|
||||||
|
|
||||||
var conditionExpression = Operator.CreateExpression(leftSideAccessor, rightSideConstant);
|
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
|
#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)
|
private void ConditionOperatorStoreOnConditionOperatorAdded(object sender, ConditionOperatorStoreEvent e)
|
||||||
{
|
{
|
||||||
var conditionOperator = e.Registration.ConditionOperator;
|
var conditionOperator = e.Registration.ConditionOperator;
|
||||||
@ -493,4 +637,25 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#endregion
|
#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;
|
Parent = parent;
|
||||||
PredicateType = predicateType;
|
PredicateType = predicateType;
|
||||||
Entity = new DisplayConditionPredicateEntity();
|
Entity = new DataModelConditionPredicateEntity();
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal DataModelConditionPredicate(DataModelConditionPart parent, DisplayConditionPredicateEntity entity)
|
internal DataModelConditionPredicate(DataModelConditionPart parent, DataModelConditionPredicateEntity entity)
|
||||||
{
|
{
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
Entity = entity;
|
Entity = entity;
|
||||||
@ -83,7 +83,7 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<DataModel, bool> CompiledStaticPredicate { get; private set; }
|
public Func<DataModel, bool> CompiledStaticPredicate { get; private set; }
|
||||||
|
|
||||||
internal DisplayConditionPredicateEntity Entity { get; set; }
|
internal DataModelConditionPredicateEntity Entity { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the left side of the predicate
|
/// Updates the left side of the predicate
|
||||||
@ -309,7 +309,7 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override DisplayConditionPartEntity GetEntity()
|
internal override DataModelConditionPartEntity GetEntity()
|
||||||
{
|
{
|
||||||
return Entity;
|
return Entity;
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ namespace Artemis.Core
|
|||||||
var rightSideAccessor = CreateAccessor(RightDataModel, RightPropertyPath, "right", out var rightSideParameter);
|
var rightSideAccessor = CreateAccessor(RightDataModel, RightPropertyPath, "right", out var rightSideParameter);
|
||||||
|
|
||||||
// A conversion may be required if the types differ
|
// 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)
|
if (rightSideAccessor.Type != leftSideAccessor.Type)
|
||||||
rightSideAccessor = Expression.Convert(rightSideAccessor, 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
|
// If the right side value is null, the constant type cannot be inferred and must be provided manually
|
||||||
var rightSideConstant = RightStaticValue != null
|
var rightSideConstant = RightStaticValue != null
|
||||||
? Expression.Constant(RightStaticValue)
|
? Expression.Constant(Convert.ChangeType(RightStaticValue, leftSideAccessor.Type))
|
||||||
: Expression.Constant(null, leftSideAccessor.Type);
|
: Expression.Constant(null, leftSideAccessor.Type);
|
||||||
|
|
||||||
var conditionExpression = Operator.CreateExpression(leftSideAccessor, rightSideConstant);
|
var conditionExpression = Operator.CreateExpression(leftSideAccessor, rightSideConstant);
|
||||||
|
|||||||
@ -72,6 +72,9 @@ namespace Artemis.Core
|
|||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
|
DataModelStore.DataModelAdded -= DataModelStoreOnDataModelAdded;
|
||||||
|
DataModelStore.DataModelRemoved -= DataModelStoreOnDataModelRemoved;
|
||||||
|
|
||||||
foreach (var dataBindingModifier in Modifiers)
|
foreach (var dataBindingModifier in Modifiers)
|
||||||
dataBindingModifier.Dispose();
|
dataBindingModifier.Dispose();
|
||||||
}
|
}
|
||||||
@ -154,7 +157,6 @@ namespace Artemis.Core
|
|||||||
return SourceDataModel?.GetTypeAtPath(SourcePropertyPath);
|
return SourceDataModel?.GetTypeAtPath(SourcePropertyPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the source of the data binding and re-compiles the expression
|
/// Updates the source of the data binding and re-compiles the expression
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -49,8 +49,8 @@ namespace Artemis.Core
|
|||||||
DisplayContinuously = RenderElementEntity.DisplayContinuously;
|
DisplayContinuously = RenderElementEntity.DisplayContinuously;
|
||||||
AlwaysFinishTimeline = RenderElementEntity.AlwaysFinishTimeline;
|
AlwaysFinishTimeline = RenderElementEntity.AlwaysFinishTimeline;
|
||||||
|
|
||||||
DataModelConditionGroup = RenderElementEntity.RootDisplayCondition != null
|
DisplayCondition = RenderElementEntity.DisplayCondition != null
|
||||||
? new DataModelConditionGroup(null, RenderElementEntity.RootDisplayCondition)
|
? new DataModelConditionGroup(null, RenderElementEntity.DisplayCondition)
|
||||||
: new DataModelConditionGroup(null);
|
: new DataModelConditionGroup(null);
|
||||||
|
|
||||||
ActivateEffects();
|
ActivateEffects();
|
||||||
@ -82,8 +82,8 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Conditions
|
// Conditions
|
||||||
RenderElementEntity.RootDisplayCondition = DataModelConditionGroup?.Entity;
|
RenderElementEntity.DisplayCondition = DisplayCondition?.Entity;
|
||||||
DataModelConditionGroup?.Save();
|
DisplayCondition?.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Properties
|
#region Properties
|
||||||
@ -392,22 +392,22 @@ namespace Artemis.Core
|
|||||||
private set => SetAndNotify(ref _displayConditionMet, value);
|
private set => SetAndNotify(ref _displayConditionMet, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataModelConditionGroup _dataModelConditionGroup;
|
private DataModelConditionGroup _displayCondition;
|
||||||
private TimeSpan _timelinePosition;
|
private TimeSpan _timelinePosition;
|
||||||
private bool _displayConditionMet;
|
private bool _displayConditionMet;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the root display condition group
|
/// Gets or sets the root display condition group
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DataModelConditionGroup DataModelConditionGroup
|
public DataModelConditionGroup DisplayCondition
|
||||||
{
|
{
|
||||||
get => _dataModelConditionGroup;
|
get => _displayCondition;
|
||||||
set => SetAndNotify(ref _dataModelConditionGroup, value);
|
set => SetAndNotify(ref _displayCondition, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateDisplayCondition()
|
public void UpdateDisplayCondition()
|
||||||
{
|
{
|
||||||
var conditionMet = DataModelConditionGroup == null || DataModelConditionGroup.Evaluate();
|
var conditionMet = DisplayCondition == null || DisplayCondition.Evaluate();
|
||||||
if (conditionMet && !DisplayConditionMet)
|
if (conditionMet && !DisplayConditionMet)
|
||||||
TimelinePosition = TimeSpan.Zero;
|
TimelinePosition = TimeSpan.Zero;
|
||||||
|
|
||||||
|
|||||||
@ -11,9 +11,9 @@ namespace Artemis.Core.Services
|
|||||||
public DataModelService(IPluginService pluginService)
|
public DataModelService(IPluginService pluginService)
|
||||||
{
|
{
|
||||||
// Add data models of already loaded plugins
|
// Add data models of already loaded plugins
|
||||||
foreach (var module in pluginService.GetPluginsOfType<Module>())
|
foreach (var module in pluginService.GetPluginsOfType<Module>().Where(p => p.Enabled))
|
||||||
AddModuleDataModel(module);
|
AddModuleDataModel(module);
|
||||||
foreach (var dataModelExpansion in pluginService.GetPluginsOfType<BaseDataModelExpansion>())
|
foreach (var dataModelExpansion in pluginService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.Enabled))
|
||||||
AddDataModelExpansionDataModel(dataModelExpansion);
|
AddDataModelExpansionDataModel(dataModelExpansion);
|
||||||
|
|
||||||
// Add data models of new plugins when they get enabled
|
// Add data models of new plugins when they get enabled
|
||||||
|
|||||||
@ -19,7 +19,7 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>A wrapper around plugin settings for internal use.</para>
|
/// <para>A wrapper around plugin settings for miscellaneous use outside plugins</para>
|
||||||
/// <para>Do not inject into a plugin, for plugins inject <see cref="PluginSettings" /> instead.</para>
|
/// <para>Do not inject into a plugin, for plugins inject <see cref="PluginSettings" /> instead.</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISettingsService : IProtectedArtemisService
|
public interface ISettingsService : IProtectedArtemisService
|
||||||
|
|||||||
@ -56,13 +56,13 @@ namespace Artemis.Core
|
|||||||
var candidates = Registrations.Where(r => r.ConditionOperator.CompatibleTypes.Any(t => t.IsCastableFrom(type))).ToList();
|
var candidates = Registrations.Where(r => r.ConditionOperator.CompatibleTypes.Any(t => t.IsCastableFrom(type))).ToList();
|
||||||
|
|
||||||
// If there are multiple operators with the same description, use the closest match
|
// If there are multiple operators with the same description, use the closest match
|
||||||
foreach (var displayConditionOperators in candidates.GroupBy(r => r.ConditionOperator.Description).Where(g => g.Count() > 1).ToList())
|
foreach (var candidate in candidates.GroupBy(r => r.ConditionOperator.Description).Where(g => g.Count() > 1).ToList())
|
||||||
{
|
{
|
||||||
var closest = displayConditionOperators.OrderByDescending(r => r.ConditionOperator.CompatibleTypes.Contains(type)).FirstOrDefault();
|
var closest = candidate.OrderByDescending(r => r.ConditionOperator.CompatibleTypes.Contains(type)).FirstOrDefault();
|
||||||
foreach (var displayConditionOperator in displayConditionOperators)
|
foreach (var conditionOperator in candidate)
|
||||||
{
|
{
|
||||||
if (displayConditionOperator != closest)
|
if (conditionOperator != closest)
|
||||||
candidates.Remove(displayConditionOperator);
|
candidates.Remove(conditionOperator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,9 @@ namespace Artemis.Plugins.DataModelExpansions.TestData.DataModels
|
|||||||
public PluginDataModel()
|
public PluginDataModel()
|
||||||
{
|
{
|
||||||
PluginSubDataModel = new PluginSubDataModel();
|
PluginSubDataModel = new PluginSubDataModel();
|
||||||
|
ListItems = new List<SomeListItem>();
|
||||||
|
for (var i = 0; i < 20; i++)
|
||||||
|
ListItems.Add(new SomeListItem {ItemName = $"Item {i + 1}", Number = i});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Your datamodel can have regular properties and you can annotate them if you'd like
|
// Your datamodel can have regular properties and you can annotate them if you'd like
|
||||||
@ -24,6 +27,14 @@ namespace Artemis.Plugins.DataModelExpansions.TestData.DataModels
|
|||||||
|
|
||||||
public Team Team { get; set; }
|
public Team Team { get; set; }
|
||||||
public bool IsWinning { get; set; }
|
public bool IsWinning { get; set; }
|
||||||
|
|
||||||
|
public List<SomeListItem> ListItems { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SomeListItem
|
||||||
|
{
|
||||||
|
public string ItemName { get; set; }
|
||||||
|
public int Number { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Team
|
public enum Team
|
||||||
@ -36,7 +47,7 @@ namespace Artemis.Plugins.DataModelExpansions.TestData.DataModels
|
|||||||
{
|
{
|
||||||
public PluginSubDataModel()
|
public PluginSubDataModel()
|
||||||
{
|
{
|
||||||
ListOfInts = new List<int> { 1, 2, 3, 4, 5 };
|
ListOfInts = new List<int> {1, 2, 3, 4, 5};
|
||||||
}
|
}
|
||||||
|
|
||||||
// You don't need to annotate properties, they will still show up
|
// You don't need to annotate properties, they will still show up
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace Artemis.Storage.Entities.Profile.Abstract
|
namespace Artemis.Storage.Entities.Profile.Abstract
|
||||||
{
|
{
|
||||||
public abstract class DisplayConditionPartEntity
|
public abstract class DataModelConditionPartEntity
|
||||||
{
|
{
|
||||||
public List<DisplayConditionPartEntity> Children { get; set; }
|
public List<DataModelConditionPartEntity> Children { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -16,6 +16,6 @@ namespace Artemis.Storage.Entities.Profile.Abstract
|
|||||||
public List<PropertyEntity> PropertyEntities { get; set; }
|
public List<PropertyEntity> PropertyEntities { get; set; }
|
||||||
public List<string> ExpandedPropertyGroups { get; set; }
|
public List<string> ExpandedPropertyGroups { get; set; }
|
||||||
|
|
||||||
public DisplayConditionGroupEntity RootDisplayCondition { get; set; }
|
public DataModelConditionGroupEntity DisplayCondition { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,11 +3,11 @@ using Artemis.Storage.Entities.Profile.Abstract;
|
|||||||
|
|
||||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionGroupEntity : DisplayConditionPartEntity
|
public class DataModelConditionGroupEntity : DataModelConditionPartEntity
|
||||||
{
|
{
|
||||||
public DisplayConditionGroupEntity()
|
public DataModelConditionGroupEntity()
|
||||||
{
|
{
|
||||||
Children = new List<DisplayConditionPartEntity>();
|
Children = new List<DataModelConditionPartEntity>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int BooleanOperator { get; set; }
|
public int BooleanOperator { get; set; }
|
||||||
@ -4,11 +4,11 @@ using Artemis.Storage.Entities.Profile.Abstract;
|
|||||||
|
|
||||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionListEntity : DisplayConditionPartEntity
|
public class DataModelConditionListEntity : DataModelConditionPartEntity
|
||||||
{
|
{
|
||||||
public DisplayConditionListEntity()
|
public DataModelConditionListEntity()
|
||||||
{
|
{
|
||||||
Children = new List<DisplayConditionPartEntity>();
|
Children = new List<DataModelConditionPartEntity>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid? ListDataModelGuid { get; set; }
|
public Guid? ListDataModelGuid { get; set; }
|
||||||
@ -3,7 +3,7 @@ using Artemis.Storage.Entities.Profile.Abstract;
|
|||||||
|
|
||||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionListPredicateEntity : DisplayConditionPartEntity
|
public class DataModelConditionListPredicateEntity : DataModelConditionPartEntity
|
||||||
{
|
{
|
||||||
public int PredicateType { get; set; }
|
public int PredicateType { get; set; }
|
||||||
|
|
||||||
@ -12,6 +12,7 @@ namespace Artemis.Storage.Entities.Profile.Conditions
|
|||||||
|
|
||||||
public string LeftPropertyPath { get; set; }
|
public string LeftPropertyPath { get; set; }
|
||||||
|
|
||||||
|
public Guid? RightDataModelGuid { get; set; }
|
||||||
public string RightPropertyPath { 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
|
||||||
@ -3,7 +3,7 @@ using Artemis.Storage.Entities.Profile.Abstract;
|
|||||||
|
|
||||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionPredicateEntity : DisplayConditionPartEntity
|
public class DataModelConditionPredicateEntity : DataModelConditionPartEntity
|
||||||
{
|
{
|
||||||
public int PredicateType { get; set; }
|
public int PredicateType { get; set; }
|
||||||
public Guid? LeftDataModelGuid { get; set; }
|
public Guid? LeftDataModelGuid { get; set; }
|
||||||
@ -1,9 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
|
||||||
{
|
|
||||||
public class ProfileConditionEntity
|
|
||||||
{
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -5,6 +5,6 @@ namespace Artemis.Storage.Entities.Profile.DataBindings
|
|||||||
public class DataBindingConditionValueEntity
|
public class DataBindingConditionValueEntity
|
||||||
{
|
{
|
||||||
public string Value { get; set; }
|
public string Value { get; set; }
|
||||||
public DisplayConditionGroupEntity RootGroup { get; set; }
|
public DataModelConditionGroupEntity RootGroup { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13,7 +13,7 @@
|
|||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DisplayConditions.xaml" />
|
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DataModelConditions.xaml" />
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||||
<shared:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
<shared:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
||||||
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
<Button Background="{Binding ButtonBrush}"
|
<Button Background="{Binding ButtonBrush}"
|
||||||
BorderBrush="{Binding ButtonBrush}"
|
BorderBrush="{Binding ButtonBrush}"
|
||||||
Style="{StaticResource DisplayConditionButton}"
|
Style="{StaticResource DataModelConditionButton}"
|
||||||
ToolTip="{Binding SelectedPropertyViewModel.DisplayPropertyPath}"
|
ToolTip="{Binding SelectedPropertyViewModel.DisplayPropertyPath}"
|
||||||
IsEnabled="{Binding IsEnabled}"
|
IsEnabled="{Binding IsEnabled}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
|
|||||||
@ -75,7 +75,7 @@ namespace Artemis.UI.Shared.Input
|
|||||||
public DataModelVisualizationViewModel SelectedPropertyViewModel
|
public DataModelVisualizationViewModel SelectedPropertyViewModel
|
||||||
{
|
{
|
||||||
get => _selectedPropertyViewModel;
|
get => _selectedPropertyViewModel;
|
||||||
private set => SetAndNotify(ref _selectedPropertyViewModel, value);
|
set => SetAndNotify(ref _selectedPropertyViewModel, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PopulateSelectedPropertyViewModel(DataModel datamodel, string path)
|
public void PopulateSelectedPropertyViewModel(DataModel datamodel, string path)
|
||||||
@ -86,6 +86,17 @@ namespace Artemis.UI.Shared.Input
|
|||||||
SelectedPropertyViewModel = DataModelViewModel.GetChildByPath(datamodel.PluginInfo.Guid, path);
|
SelectedPropertyViewModel = DataModelViewModel.GetChildByPath(datamodel.PluginInfo.Guid, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ChangeDataModel(DataModelPropertiesViewModel dataModel)
|
||||||
|
{
|
||||||
|
if (DataModelViewModel != null)
|
||||||
|
DataModelViewModel.UpdateRequested -= DataModelOnUpdateRequested;
|
||||||
|
|
||||||
|
DataModelViewModel = dataModel;
|
||||||
|
|
||||||
|
if (DataModelViewModel != null)
|
||||||
|
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
|
||||||
|
}
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
// Get the data models
|
// Get the data models
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DisplayConditions.xaml" />
|
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DataModelConditions.xaml" />
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
@ -22,12 +22,13 @@
|
|||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
|
|
||||||
<materialDesign:Transitioner SelectedIndex="{Binding TransitionIndex}" DefaultTransitionOrigin="0.5, 0.5" Margin="3 -4">
|
<materialDesign:Transitioner SelectedIndex="{Binding TransitionIndex}" DefaultTransitionOrigin="0.5, 0.5" Margin="3 -4">
|
||||||
<Button Style="{StaticResource DisplayConditionButton}"
|
<Button Style="{StaticResource DataModelConditionButton}"
|
||||||
Background="{Binding ButtonBrush}"
|
Background="{Binding ButtonBrush}"
|
||||||
BorderBrush="{Binding ButtonBrush}"
|
BorderBrush="{Binding ButtonBrush}"
|
||||||
Margin="0 4"
|
Margin="0 4"
|
||||||
Command="{s:Action ActivateInputViewModel}"
|
Command="{s:Action ActivateInputViewModel}"
|
||||||
HorizontalAlignment="Left">
|
HorizontalAlignment="Left"
|
||||||
|
IsEnabled="{Binding IsEnabled}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<StackPanel Visibility="{Binding Value, Converter={StaticResource NullToVisibilityConverter}}" Orientation="Horizontal">
|
<StackPanel Visibility="{Binding Value, Converter={StaticResource NullToVisibilityConverter}}" Orientation="Horizontal">
|
||||||
<TextBlock FontWeight="Light"
|
<TextBlock FontWeight="Light"
|
||||||
|
|||||||
@ -22,15 +22,17 @@ namespace Artemis.UI.Shared.Input
|
|||||||
private Type _targetType;
|
private Type _targetType;
|
||||||
private int _transitionIndex;
|
private int _transitionIndex;
|
||||||
private object _value;
|
private object _value;
|
||||||
|
private bool _isEnabled;
|
||||||
|
|
||||||
internal DataModelStaticViewModel(Type targetType, IDataModelUIService dataModelUIService)
|
internal DataModelStaticViewModel(Type targetType, IDataModelUIService dataModelUIService)
|
||||||
{
|
{
|
||||||
TargetType = targetType;
|
|
||||||
_dataModelUIService = dataModelUIService;
|
_dataModelUIService = dataModelUIService;
|
||||||
|
|
||||||
DisplayViewModel = _dataModelUIService.GetDataModelDisplayViewModel(TargetType, true);
|
|
||||||
|
|
||||||
_rootView = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
|
_rootView = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
|
||||||
|
|
||||||
|
TargetType = targetType;
|
||||||
|
IsEnabled = TargetType != null;
|
||||||
|
DisplayViewModel = _dataModelUIService.GetDataModelDisplayViewModel(TargetType ?? typeof(object), true);
|
||||||
|
|
||||||
if (_rootView != null)
|
if (_rootView != null)
|
||||||
{
|
{
|
||||||
_rootView.MouseUp += RootViewOnMouseUp;
|
_rootView.MouseUp += RootViewOnMouseUp;
|
||||||
@ -90,6 +92,12 @@ namespace Artemis.UI.Shared.Input
|
|||||||
set => SetAndNotify(ref _placeholder, value);
|
set => SetAndNotify(ref _placeholder, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsEnabled
|
||||||
|
{
|
||||||
|
get => _isEnabled;
|
||||||
|
private set => SetAndNotify(ref _isEnabled, value);
|
||||||
|
}
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
@ -116,14 +124,24 @@ namespace Artemis.UI.Shared.Input
|
|||||||
|
|
||||||
public void UpdateTargetType(Type target)
|
public void UpdateTargetType(Type target)
|
||||||
{
|
{
|
||||||
TargetType = target ?? throw new ArgumentNullException(nameof(target));
|
TargetType = target;
|
||||||
|
DisplayViewModel = _dataModelUIService.GetDataModelDisplayViewModel(TargetType ?? typeof(object), true);
|
||||||
|
IsEnabled = TargetType != null;
|
||||||
|
|
||||||
|
// If null, clear the input
|
||||||
|
if (TargetType == null)
|
||||||
|
{
|
||||||
|
ApplyFreeInput(null, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If the type changed, reset to the default type
|
// If the type changed, reset to the default type
|
||||||
if (!target.IsCastableFrom(Value.GetType()))
|
if (Value == null || !target.IsCastableFrom(Value.GetType()))
|
||||||
{
|
{
|
||||||
// Force the VM to close if it was open and apply the new value
|
// Force the VM to close if it was open and apply the new value
|
||||||
ApplyFreeInput(target.GetDefault(), true);
|
ApplyFreeInput(target.GetDefault(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyFreeInput(object value, bool submitted)
|
private void ApplyFreeInput(object value, bool submitted)
|
||||||
|
|||||||
@ -36,7 +36,7 @@ namespace Artemis.UI.Shared
|
|||||||
public DataModelPropertiesViewModel GetListTypeViewModel(IDataModelUIService dataModelUIService)
|
public DataModelPropertiesViewModel GetListTypeViewModel(IDataModelUIService dataModelUIService)
|
||||||
{
|
{
|
||||||
// Create a property VM describing the type of the list
|
// Create a property VM describing the type of the list
|
||||||
var viewModel = CreateListChild(dataModelUIService, List.GetType().GenericTypeArguments[0]);
|
var viewModel = CreateListChild(dataModelUIService, PropertyInfo.PropertyType.GenericTypeArguments[0]);
|
||||||
|
|
||||||
// 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)
|
||||||
|
|||||||
@ -176,9 +176,9 @@ namespace Artemis.UI.Shared
|
|||||||
IsMatchingFilteredTypes = filteredTypes.Any(t => t == PropertyInfo.PropertyType || t == typeof(Enum) && PropertyInfo.PropertyType.IsEnum);
|
IsMatchingFilteredTypes = filteredTypes.Any(t => t == PropertyInfo.PropertyType || t == typeof(Enum) && PropertyInfo.PropertyType.IsEnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataModelVisualizationViewModel GetChildForCondition(DataModelConditionPredicate predicate, DisplayConditionSide side)
|
public DataModelVisualizationViewModel GetChildForCondition(DataModelConditionPredicate predicate, DataModelConditionSide side)
|
||||||
{
|
{
|
||||||
if (side == DisplayConditionSide.Left)
|
if (side == DataModelConditionSide.Left)
|
||||||
{
|
{
|
||||||
if (predicate.LeftDataModel == null || predicate.LeftPropertyPath == null)
|
if (predicate.LeftDataModel == null || predicate.LeftPropertyPath == null)
|
||||||
return null;
|
return null;
|
||||||
@ -289,7 +289,7 @@ namespace Artemis.UI.Shared
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DisplayConditionSide
|
public enum DataModelConditionSide
|
||||||
{
|
{
|
||||||
Left,
|
Left,
|
||||||
Right
|
Right
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<!-- Value display -->
|
<!-- Value display -->
|
||||||
<TextBlock Text="{Binding DisplayValue, Mode=OneWay}"
|
<TextBlock Text="{Binding DisplayValue, Mode=OneWay}"
|
||||||
FontFamily="Consolas"
|
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Visibility="{Binding ShowToString, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
|
Visibility="{Binding ShowToString, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
|
||||||
<TextBlock Text="null"
|
<TextBlock Text="null"
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
xmlns:dataModel="clr-namespace:Artemis.UI.Shared">
|
xmlns:dataModel="clr-namespace:Artemis.UI.Shared">
|
||||||
<Style x:Key="DisplayConditionButton" TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignFlatAccentBgButton}">
|
<Style x:Key="DataModelConditionButton" TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignFlatAccentBgButton}">
|
||||||
<Setter Property="Margin" Value="3 0" />
|
<Setter Property="Margin" Value="3 0" />
|
||||||
<Setter Property="Padding" Value="6 4" />
|
<Setter Property="Padding" Value="6 4" />
|
||||||
<Setter Property="Height" Value="22" />
|
<Setter Property="Height" Value="22" />
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<Setter Property="FontSize" Value="12" />
|
<Setter Property="FontSize" Value="12" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style x:Key="DisplayConditionButtonLeftClickMenu" TargetType="{x:Type Button}" BasedOn="{StaticResource DisplayConditionButton}">
|
<Style x:Key="DataModelConditionButtonLeftClickMenu" TargetType="{x:Type Button}" BasedOn="{StaticResource DataModelConditionButton}">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<EventTrigger RoutedEvent="Click">
|
<EventTrigger RoutedEvent="Click">
|
||||||
<EventTrigger.Actions>
|
<EventTrigger.Actions>
|
||||||
@ -201,7 +201,6 @@ namespace Artemis.UI.Shared.Services
|
|||||||
|
|
||||||
public DataModelStaticViewModel GetStaticInputViewModel(Type targetType)
|
public DataModelStaticViewModel GetStaticInputViewModel(Type targetType)
|
||||||
{
|
{
|
||||||
if (targetType == null) throw new ArgumentNullException(nameof(targetType));
|
|
||||||
return _kernel.Get<DataModelStaticViewModel>(new ConstructorArgument("targetType", targetType));
|
return _kernel.Get<DataModelStaticViewModel>(new ConstructorArgument("targetType", targetType));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -215,10 +215,10 @@
|
|||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.i.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.i.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.i.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\Dialogs\ProfileElementRenameView.g.i.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DisplayConditions\DisplayConditionsView.g.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DisplayConditions\DisplayConditionsView.g.i.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.i.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DisplayConditions\DisplayConditionView.g.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DisplayConditions\DisplayConditionView.g.i.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.i.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.i.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.i.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.i.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.i.cs" />
|
||||||
@ -239,8 +239,8 @@
|
|||||||
<Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.i.cs" />
|
<Compile Remove="obj\x64\Debug\Screens\Settings\Tabs\Devices\DeviceSettingsView.g.i.cs" />
|
||||||
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" />
|
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\Dialogs\ProfileCreateView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DisplayConditions\DisplayConditionsView.g.cs" />
|
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionsView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DisplayConditions\DisplayConditionView.g.cs" />
|
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\DataModelConditions\DataModelConditionView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.cs" />
|
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertiesView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" />
|
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\ElementProperties\ElementPropertyView.g.cs" />
|
||||||
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.cs" />
|
<Compile Remove="obj\x64\Release\Screens\Module\ProfileEditor\LayerElements\LayerElementsView.g.cs" />
|
||||||
|
|||||||
@ -3,7 +3,7 @@ using Artemis.Core.Modules;
|
|||||||
using Artemis.UI.Screens.Modules;
|
using Artemis.UI.Screens.Modules;
|
||||||
using Artemis.UI.Screens.Modules.Tabs;
|
using Artemis.UI.Screens.Modules.Tabs;
|
||||||
using Artemis.UI.Screens.ProfileEditor;
|
using Artemis.UI.Screens.ProfileEditor;
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
|
using Artemis.UI.Screens.ProfileEditor.Conditions;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings;
|
||||||
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.ConditionalDataBinding;
|
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.ConditionalDataBinding;
|
||||||
@ -63,12 +63,12 @@ namespace Artemis.UI.Ninject.Factories
|
|||||||
SelectionRemoveToolViewModel SelectionRemoveToolViewModel(ProfileViewModel profileViewModel);
|
SelectionRemoveToolViewModel SelectionRemoveToolViewModel(ProfileViewModel profileViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IDisplayConditionsVmFactory : IVmFactory
|
public interface IDataModelConditionsVmFactory : IVmFactory
|
||||||
{
|
{
|
||||||
DisplayConditionGroupViewModel DisplayConditionGroupViewModel(DataModelConditionGroup dataModelConditionGroup, bool isListGroup);
|
DataModelConditionGroupViewModel DataModelConditionGroupViewModel(DataModelConditionGroup dataModelConditionGroup, bool isListGroup);
|
||||||
DisplayConditionListViewModel DisplayConditionListViewModel(DataModelConditionList dataModelConditionList);
|
DataModelConditionListViewModel DataModelConditionListViewModel(DataModelConditionList dataModelConditionList);
|
||||||
DisplayConditionPredicateViewModel DisplayConditionPredicateViewModel(DataModelConditionPredicate dataModelConditionPredicate);
|
DataModelConditionPredicateViewModel DataModelConditionPredicateViewModel(DataModelConditionPredicate dataModelConditionPredicate);
|
||||||
DisplayConditionListPredicateViewModel DisplayConditionListPredicateViewModel(DataModelConditionListPredicate dataModelConditionListPredicate);
|
DataModelConditionListPredicateViewModel DataModelConditionListPredicateViewModel(DataModelConditionListPredicate dataModelConditionListPredicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ILayerPropertyVmFactory : IVmFactory
|
public interface ILayerPropertyVmFactory : IVmFactory
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
xmlns:dataModel="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared">
|
xmlns:dataModel="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared">
|
||||||
<Style x:Key="DisplayConditionButton" TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignFlatAccentBgButton}">
|
<Style x:Key="DataModelConditionButton" TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignFlatAccentBgButton}">
|
||||||
<Setter Property="Margin" Value="3 0" />
|
<Setter Property="Margin" Value="3 0" />
|
||||||
<Setter Property="Padding" Value="6 4" />
|
<Setter Property="Padding" Value="6 4" />
|
||||||
<Setter Property="Height" Value="22" />
|
<Setter Property="Height" Value="22" />
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<Setter Property="FontSize" Value="12" />
|
<Setter Property="FontSize" Value="12" />
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
<Style x:Key="DisplayConditionButtonLeftClickMenu" TargetType="{x:Type Button}" BasedOn="{StaticResource DisplayConditionButton}">
|
<Style x:Key="DataModelConditionButtonLeftClickMenu" TargetType="{x:Type Button}" BasedOn="{StaticResource DataModelConditionButton}">
|
||||||
<Style.Triggers>
|
<Style.Triggers>
|
||||||
<EventTrigger RoutedEvent="Click">
|
<EventTrigger RoutedEvent="Click">
|
||||||
<EventTrigger.Actions>
|
<EventTrigger.Actions>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
using Artemis.Core;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions.Abstract
|
||||||
|
{
|
||||||
|
public abstract class DataModelConditionViewModel : Conductor<DataModelConditionViewModel>.Collection.AllActive
|
||||||
|
{
|
||||||
|
protected DataModelConditionViewModel(DataModelConditionPart model)
|
||||||
|
{
|
||||||
|
Model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelConditionPart Model { get; }
|
||||||
|
|
||||||
|
public abstract void Update();
|
||||||
|
|
||||||
|
public virtual void Delete()
|
||||||
|
{
|
||||||
|
Model.Parent.RemoveChild(Model);
|
||||||
|
((DataModelConditionViewModel) Parent).Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,19 +3,19 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
xmlns:Converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:Converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
|
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.DisplayConditionGroupView"
|
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.Conditions"
|
||||||
|
x:Class="Artemis.UI.Screens.ProfileEditor.Conditions.DataModelConditionGroupView"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=False, Type={x:Type local:DisplayConditionGroupViewModel}}">
|
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=False, Type={x:Type local:DataModelConditionGroupViewModel}}">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DisplayConditions.xaml" />
|
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DataModelConditions.xaml" />
|
||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
@ -46,7 +46,7 @@
|
|||||||
<Button Grid.Row="0"
|
<Button Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
ToolTip="Change the operator of the group"
|
ToolTip="Change the operator of the group"
|
||||||
Style="{StaticResource DisplayConditionButtonLeftClickMenu}"
|
Style="{StaticResource DataModelConditionButtonLeftClickMenu}"
|
||||||
Background="#E74C4C"
|
Background="#E74C4C"
|
||||||
BorderBrush="#E74C4C"
|
BorderBrush="#E74C4C"
|
||||||
Margin="3 1"
|
Margin="3 1"
|
||||||
@ -3,29 +3,30 @@ using System.Linq;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
using Artemis.UI.Screens.ProfileEditor.Conditions.Abstract;
|
||||||
|
using Artemis.UI.Screens.ProfileEditor.DisplayConditions;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionGroupViewModel : DisplayConditionViewModel
|
public class DataModelConditionGroupViewModel : DataModelConditionViewModel
|
||||||
{
|
{
|
||||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
private readonly IDataModelConditionsVmFactory _dataModelConditionsVmFactory;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
private bool _isRootGroup;
|
private bool _isRootGroup;
|
||||||
|
|
||||||
public DisplayConditionGroupViewModel(DataModelConditionGroup dataModelConditionGroup,
|
public DataModelConditionGroupViewModel(DataModelConditionGroup dataModelConditionGroup,
|
||||||
bool isListGroup,
|
bool isListGroup,
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IDisplayConditionsVmFactory displayConditionsVmFactory)
|
IDataModelConditionsVmFactory dataModelConditionsVmFactory)
|
||||||
: base(dataModelConditionGroup)
|
: base(dataModelConditionGroup)
|
||||||
{
|
{
|
||||||
IsListGroup = isListGroup;
|
IsListGroup = isListGroup;
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_displayConditionsVmFactory = displayConditionsVmFactory;
|
_dataModelConditionsVmFactory = dataModelConditionsVmFactory;
|
||||||
|
|
||||||
Items.CollectionChanged += (sender, args) => NotifyOfPropertyChange(nameof(DisplayBooleanOperator));
|
Items.CollectionChanged += (sender, args) => NotifyOfPropertyChange(nameof(DisplayBooleanOperator));
|
||||||
|
|
||||||
@ -71,15 +72,17 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
if (!IsListGroup)
|
if (!IsListGroup)
|
||||||
DataModelConditionGroup.AddChild(new DataModelConditionPredicate(DataModelConditionGroup, ProfileRightSideType.Static));
|
DataModelConditionGroup.AddChild(new DataModelConditionPredicate(DataModelConditionGroup, ProfileRightSideType.Static));
|
||||||
else
|
else
|
||||||
DataModelConditionGroup.AddChild(new DataModelConditionListPredicate(DataModelConditionGroup, ProfileRightSideType.Static));
|
DataModelConditionGroup.AddChild(new DataModelConditionListPredicate(DataModelConditionGroup, ListRightSideType.Static));
|
||||||
}
|
}
|
||||||
else if (type == "Dynamic")
|
else if (type == "Dynamic")
|
||||||
{
|
{
|
||||||
if (!IsListGroup)
|
if (!IsListGroup)
|
||||||
DataModelConditionGroup.AddChild(new DataModelConditionPredicate(DataModelConditionGroup, ProfileRightSideType.Dynamic));
|
DataModelConditionGroup.AddChild(new DataModelConditionPredicate(DataModelConditionGroup, ProfileRightSideType.Dynamic));
|
||||||
else
|
else
|
||||||
DataModelConditionGroup.AddChild(new DataModelConditionListPredicate(DataModelConditionGroup, ProfileRightSideType.Dynamic));
|
DataModelConditionGroup.AddChild(new DataModelConditionListPredicate(DataModelConditionGroup, ListRightSideType.Dynamic));
|
||||||
}
|
}
|
||||||
|
else if (type == "DynamicExternal" && IsListGroup)
|
||||||
|
DataModelConditionGroup.AddChild(new DataModelConditionListPredicate(DataModelConditionGroup, ListRightSideType.DynamicExternal));
|
||||||
else if (type == "List" && !IsListGroup)
|
else if (type == "List" && !IsListGroup)
|
||||||
DataModelConditionGroup.AddChild(new DataModelConditionList(DataModelConditionGroup));
|
DataModelConditionGroup.AddChild(new DataModelConditionList(DataModelConditionGroup));
|
||||||
|
|
||||||
@ -102,8 +105,8 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
// Remove VMs of effects no longer applied on the layer
|
// Remove VMs of effects no longer applied on the layer
|
||||||
var toRemove = Items.Where(c => !DataModelConditionGroup.Children.Contains(c.Model)).ToList();
|
var toRemove = Items.Where(c => !DataModelConditionGroup.Children.Contains(c.Model)).ToList();
|
||||||
// Using RemoveRange breaks our lovely animations
|
// Using RemoveRange breaks our lovely animations
|
||||||
foreach (var displayConditionViewModel in toRemove)
|
foreach (var DataModelConditionViewModel in toRemove)
|
||||||
Items.Remove(displayConditionViewModel);
|
Items.Remove(DataModelConditionViewModel);
|
||||||
|
|
||||||
foreach (var childModel in Model.Children)
|
foreach (var childModel in Model.Children)
|
||||||
{
|
{
|
||||||
@ -112,19 +115,19 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
|
|
||||||
switch (childModel)
|
switch (childModel)
|
||||||
{
|
{
|
||||||
case DataModelConditionGroup displayConditionGroup:
|
case DataModelConditionGroup DataModelConditionGroup:
|
||||||
Items.Add(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, IsListGroup));
|
Items.Add(_dataModelConditionsVmFactory.DataModelConditionGroupViewModel(DataModelConditionGroup, IsListGroup));
|
||||||
break;
|
break;
|
||||||
case DataModelConditionList displayConditionListPredicate:
|
case DataModelConditionList DataModelConditionListPredicate:
|
||||||
Items.Add(_displayConditionsVmFactory.DisplayConditionListViewModel(displayConditionListPredicate));
|
Items.Add(_dataModelConditionsVmFactory.DataModelConditionListViewModel(DataModelConditionListPredicate));
|
||||||
break;
|
break;
|
||||||
case DataModelConditionPredicate displayConditionPredicate:
|
case DataModelConditionPredicate DataModelConditionPredicate:
|
||||||
if (!IsListGroup)
|
if (!IsListGroup)
|
||||||
Items.Add(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate));
|
Items.Add(_dataModelConditionsVmFactory.DataModelConditionPredicateViewModel(DataModelConditionPredicate));
|
||||||
break;
|
break;
|
||||||
case DataModelConditionListPredicate displayConditionListPredicate:
|
case DataModelConditionListPredicate DataModelConditionListPredicate:
|
||||||
if (IsListGroup)
|
if (IsListGroup)
|
||||||
Items.Add(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate));
|
Items.Add(_dataModelConditionsVmFactory.DataModelConditionListPredicateViewModel(DataModelConditionListPredicate));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,8 +135,8 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
foreach (var childViewModel in Items)
|
foreach (var childViewModel in Items)
|
||||||
childViewModel.Update();
|
childViewModel.Update();
|
||||||
|
|
||||||
if (IsRootGroup)
|
if (IsRootGroup && Parent is DisplayConditionsViewModel displayConditionsViewModel)
|
||||||
((DisplayConditionsViewModel) Parent).DisplayStartHint = !Items.Any();
|
displayConditionsViewModel.DisplayStartHint = !Items.Any();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
<UserControl
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
|
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
|
||||||
|
xmlns:DataModelConditions="clr-namespace:Artemis.UI.Screens.ProfileEditor.Conditions"
|
||||||
|
x:Class="Artemis.UI.Screens.ProfileEditor.Conditions.DataModelConditionListPredicateView"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=False, Type={x:Type DataModelConditions:DataModelConditionListPredicateViewModel}}">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DataModelConditions.xaml" />
|
||||||
|
<ResourceDictionary>
|
||||||
|
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||||
|
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
||||||
|
<DataTemplate x:Key="DataModelDataTemplate">
|
||||||
|
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
|
||||||
|
<DataTemplate.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
|
||||||
|
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
|
||||||
|
</DataTrigger>
|
||||||
|
</DataTemplate.Triggers>
|
||||||
|
</DataTemplate>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Grid Margin="0 3">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
ToolTip="Delete the predicate"
|
||||||
|
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Foreground="#E74C4C"
|
||||||
|
Width="25"
|
||||||
|
Height="25"
|
||||||
|
Command="{s:Action Delete}">
|
||||||
|
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Left side, may be null for primitive lists -->
|
||||||
|
<ContentControl Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
s:View.Model="{Binding LeftSideSelectionViewModel}"
|
||||||
|
VerticalContentAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
IsTabStop="False" />
|
||||||
|
|
||||||
|
<!-- Operator -->
|
||||||
|
<Button Grid.Row="0"
|
||||||
|
Grid.Column="2"
|
||||||
|
Style="{StaticResource DataModelConditionButtonLeftClickMenu}"
|
||||||
|
Background="#7B7B7B"
|
||||||
|
BorderBrush="#7B7B7B"
|
||||||
|
Content="{Binding SelectedOperator.Description}"
|
||||||
|
Click="PropertyButton_OnClick">
|
||||||
|
<Button.ContextMenu>
|
||||||
|
<ContextMenu ItemsSource="{Binding Operators}">
|
||||||
|
<ContextMenu.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:PackIcon Kind="{Binding Icon}" VerticalAlignment="Center" Margin="0 0 15 0" />
|
||||||
|
<TextBlock Text="{Binding Description}" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ContextMenu.ItemTemplate>
|
||||||
|
<ContextMenu.ItemContainerStyle>
|
||||||
|
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
||||||
|
<Setter Property="Command" Value="{Binding Data.SelectOperatorCommand, Source={StaticResource DataContextProxy}}" />
|
||||||
|
<Setter Property="CommandParameter" Value="{Binding}" />
|
||||||
|
<Setter Property="CommandTarget" Value="{Binding}" />
|
||||||
|
</Style>
|
||||||
|
</ContextMenu.ItemContainerStyle>
|
||||||
|
</ContextMenu>
|
||||||
|
</Button.ContextMenu>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Right side, either a selection or an input -->
|
||||||
|
<ContentControl Grid.Row="0"
|
||||||
|
Grid.Column="3"
|
||||||
|
s:View.Model="{Binding RightSideSelectionViewModel}"
|
||||||
|
VerticalContentAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
IsTabStop="False" />
|
||||||
|
<ContentControl Grid.Row="0"
|
||||||
|
Grid.Column="3"
|
||||||
|
s:View.Model="{Binding RightSideInputViewModel}"
|
||||||
|
VerticalContentAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
IsTabStop="False" />
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@ -1,14 +1,14 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for DisplayConditionListPredicateView.xaml
|
/// Interaction logic for DataModelConditionListPredicateView.xaml
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class DisplayConditionListPredicateView : UserControl
|
public partial class DataModelConditionListPredicateView : UserControl
|
||||||
{
|
{
|
||||||
public DisplayConditionListPredicateView()
|
public DataModelConditionListPredicateView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
@ -0,0 +1,285 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Exceptions;
|
||||||
|
using Artemis.UI.Screens.ProfileEditor.Conditions.Abstract;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Input;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||||
|
{
|
||||||
|
public class DataModelConditionListPredicateViewModel : DataModelConditionViewModel, IDisposable
|
||||||
|
{
|
||||||
|
private readonly IConditionOperatorService _conditionOperatorService;
|
||||||
|
private readonly IDataModelUIService _dataModelUIService;
|
||||||
|
private readonly IEventAggregator _eventAggregator;
|
||||||
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
|
private bool _isPrimitiveList;
|
||||||
|
private DataModelDynamicViewModel _leftSideSelectionViewModel;
|
||||||
|
private BindableCollection<ConditionOperator> _operators;
|
||||||
|
private DataModelStaticViewModel _rightSideInputViewModel;
|
||||||
|
private DataModelDynamicViewModel _rightSideSelectionViewModel;
|
||||||
|
private ConditionOperator _selectedOperator;
|
||||||
|
|
||||||
|
private List<Type> _supportedInputTypes;
|
||||||
|
|
||||||
|
public DataModelConditionListPredicateViewModel(
|
||||||
|
DataModelConditionListPredicate dataModelConditionListPredicate,
|
||||||
|
IProfileEditorService profileEditorService,
|
||||||
|
IDataModelUIService dataModelUIService,
|
||||||
|
IConditionOperatorService conditionOperatorService,
|
||||||
|
IEventAggregator eventAggregator) : base(dataModelConditionListPredicate)
|
||||||
|
{
|
||||||
|
_profileEditorService = profileEditorService;
|
||||||
|
_dataModelUIService = dataModelUIService;
|
||||||
|
_conditionOperatorService = conditionOperatorService;
|
||||||
|
_eventAggregator = eventAggregator;
|
||||||
|
_supportedInputTypes = new List<Type>();
|
||||||
|
|
||||||
|
SelectOperatorCommand = new DelegateCommand(ExecuteSelectOperatorCommand);
|
||||||
|
Operators = new BindableCollection<ConditionOperator>();
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelConditionListPredicate DataModelConditionListPredicate => (DataModelConditionListPredicate) Model;
|
||||||
|
|
||||||
|
public BindableCollection<ConditionOperator> Operators
|
||||||
|
{
|
||||||
|
get => _operators;
|
||||||
|
set => SetAndNotify(ref _operators, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelDynamicViewModel LeftSideSelectionViewModel
|
||||||
|
{
|
||||||
|
get => _leftSideSelectionViewModel;
|
||||||
|
set => SetAndNotify(ref _leftSideSelectionViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelDynamicViewModel RightSideSelectionViewModel
|
||||||
|
{
|
||||||
|
get => _rightSideSelectionViewModel;
|
||||||
|
set => SetAndNotify(ref _rightSideSelectionViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelStaticViewModel RightSideInputViewModel
|
||||||
|
{
|
||||||
|
get => _rightSideInputViewModel;
|
||||||
|
set => SetAndNotify(ref _rightSideInputViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConditionOperator SelectedOperator
|
||||||
|
{
|
||||||
|
get => _selectedOperator;
|
||||||
|
set => SetAndNotify(ref _selectedOperator, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelegateCommand SelectOperatorCommand { get; }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_isPrimitiveList)
|
||||||
|
{
|
||||||
|
LeftSideSelectionViewModel.PropertySelected -= LeftSideOnPropertySelected;
|
||||||
|
LeftSideSelectionViewModel.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
DisposeRightSideDynamic();
|
||||||
|
DisposeRightSideStatic();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Delete()
|
||||||
|
{
|
||||||
|
base.Delete();
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
var listDataModel = GetListDataModel();
|
||||||
|
if (listDataModel.Children.Count == 1 && listDataModel.Children.First() is DataModelListPropertyViewModel)
|
||||||
|
_isPrimitiveList = true;
|
||||||
|
else
|
||||||
|
_isPrimitiveList = false;
|
||||||
|
|
||||||
|
// Get the data models
|
||||||
|
if (!_isPrimitiveList)
|
||||||
|
{
|
||||||
|
LeftSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
||||||
|
LeftSideSelectionViewModel.ChangeDataModel((DataModelPropertiesViewModel) listDataModel);
|
||||||
|
LeftSideSelectionViewModel.PropertySelected += LeftSideOnPropertySelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine which types are currently supported
|
||||||
|
var editors = _dataModelUIService.RegisteredDataModelEditors;
|
||||||
|
_supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
|
||||||
|
_supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes));
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
var listDataModelGuid = DataModelConditionListPredicate.ListDataModel.PluginInfo.Guid;
|
||||||
|
if (!_isPrimitiveList)
|
||||||
|
{
|
||||||
|
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
|
||||||
|
LeftSideSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(71, 108, 188));
|
||||||
|
LeftSideSelectionViewModel.SelectedPropertyViewModel = LeftSideSelectionViewModel.DataModelViewModel.GetChildByPath(
|
||||||
|
listDataModelGuid, DataModelConditionListPredicate.LeftPropertyPath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var leftSideType = _isPrimitiveList
|
||||||
|
? DataModelConditionListPredicate.ListType
|
||||||
|
: LeftSideSelectionViewModel.SelectedPropertyViewModel?.PropertyInfo?.PropertyType;
|
||||||
|
|
||||||
|
// Get the supported operators
|
||||||
|
Operators.Clear();
|
||||||
|
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
||||||
|
if (DataModelConditionListPredicate.Operator == null)
|
||||||
|
DataModelConditionListPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
||||||
|
SelectedOperator = DataModelConditionListPredicate.Operator;
|
||||||
|
|
||||||
|
// Ensure the right side has the proper VM
|
||||||
|
if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic || DataModelConditionListPredicate.PredicateType == ListRightSideType.DynamicExternal)
|
||||||
|
{
|
||||||
|
DisposeRightSideStatic();
|
||||||
|
if (RightSideSelectionViewModel == null)
|
||||||
|
{
|
||||||
|
RightSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
||||||
|
RightSideSelectionViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
|
||||||
|
RightSideSelectionViewModel.PropertySelected += RightSideOnPropertySelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
RightSideSelectionViewModel.FilterTypes = new[] {leftSideType};
|
||||||
|
if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic)
|
||||||
|
{
|
||||||
|
RightSideSelectionViewModel.SelectedPropertyViewModel = RightSideSelectionViewModel.DataModelViewModel.GetChildByPath(
|
||||||
|
listDataModelGuid, DataModelConditionListPredicate.RightPropertyPath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(DataModelConditionListPredicate.RightDataModel, DataModelConditionListPredicate.RightPropertyPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DisposeRightSideDynamic();
|
||||||
|
if (RightSideInputViewModel == null)
|
||||||
|
{
|
||||||
|
RightSideInputViewModel = _dataModelUIService.GetStaticInputViewModel(leftSideType);
|
||||||
|
RightSideInputViewModel.Value = DataModelConditionListPredicate.RightStaticValue;
|
||||||
|
RightSideInputViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
|
||||||
|
RightSideInputViewModel.ValueUpdated += RightSideOnValueEntered;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RightSideInputViewModel.TargetType != leftSideType)
|
||||||
|
RightSideInputViewModel.UpdateTargetType(leftSideType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyLeftSide()
|
||||||
|
{
|
||||||
|
DataModelConditionListPredicate.UpdateLeftSide(LeftSideSelectionViewModel.SelectedPropertyViewModel.PropertyPath);
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
SelectedOperator = DataModelConditionListPredicate.Operator;
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyRightSideDynamic()
|
||||||
|
{
|
||||||
|
if (DataModelConditionListPredicate.ListContainsInnerPath(RightSideSelectionViewModel.SelectedPropertyViewModel.PropertyPath))
|
||||||
|
DataModelConditionListPredicate.UpdateRightSideDynamic(RightSideSelectionViewModel.SelectedPropertyViewModel.PropertyPath);
|
||||||
|
else
|
||||||
|
DataModelConditionListPredicate.UpdateRightSideDynamic(
|
||||||
|
RightSideSelectionViewModel.SelectedPropertyViewModel.DataModel,
|
||||||
|
RightSideSelectionViewModel.SelectedPropertyViewModel.PropertyPath
|
||||||
|
);
|
||||||
|
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyRightSideStatic(object value)
|
||||||
|
{
|
||||||
|
DataModelConditionListPredicate.UpdateRightSideStatic(value);
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyOperator()
|
||||||
|
{
|
||||||
|
DataModelConditionListPredicate.UpdateOperator(SelectedOperator);
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataModelVisualizationViewModel GetListDataModel()
|
||||||
|
{
|
||||||
|
if (DataModelConditionListPredicate.ListDataModel == null || DataModelConditionListPredicate.ListPropertyPath == null)
|
||||||
|
throw new ArtemisUIException("Cannot create a list predicate without first selecting a target list");
|
||||||
|
|
||||||
|
var dataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
||||||
|
var listDataModel = (DataModelListViewModel) dataModel.GetChildByPath(
|
||||||
|
DataModelConditionListPredicate.ListDataModel.PluginInfo.Guid,
|
||||||
|
DataModelConditionListPredicate.ListPropertyPath
|
||||||
|
);
|
||||||
|
|
||||||
|
return listDataModel.GetListTypeViewModel(_dataModelUIService);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExecuteSelectOperatorCommand(object context)
|
||||||
|
{
|
||||||
|
if (!(context is ConditionOperator dataModelConditionOperator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SelectedOperator = dataModelConditionOperator;
|
||||||
|
ApplyOperator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LeftSideOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
|
||||||
|
{
|
||||||
|
ApplyLeftSide();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RightSideOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
|
||||||
|
{
|
||||||
|
ApplyRightSideDynamic();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RightSideOnValueEntered(object sender, DataModelInputStaticEventArgs e)
|
||||||
|
{
|
||||||
|
ApplyRightSideStatic(e.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeRightSideStatic()
|
||||||
|
{
|
||||||
|
if (RightSideInputViewModel != null)
|
||||||
|
{
|
||||||
|
RightSideInputViewModel.ValueUpdated -= RightSideOnValueEntered;
|
||||||
|
RightSideInputViewModel.Dispose();
|
||||||
|
RightSideInputViewModel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeRightSideDynamic()
|
||||||
|
{
|
||||||
|
if (RightSideSelectionViewModel != null)
|
||||||
|
{
|
||||||
|
RightSideSelectionViewModel.PropertySelected -= RightSideOnPropertySelected;
|
||||||
|
RightSideSelectionViewModel.Dispose();
|
||||||
|
RightSideSelectionViewModel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.Conditions.DataModelConditionListView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.Conditions"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance Type=local:DataModelConditionListViewModel, IsDesignTimeCreatable=False}">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DataModelConditions.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Grid Margin="0 3">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
ToolTip="Delete the list predicate and all its children"
|
||||||
|
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Foreground="#E74C4C"
|
||||||
|
Width="25"
|
||||||
|
Height="25"
|
||||||
|
Command="{s:Action Delete}">
|
||||||
|
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Left side, the list this predicate is targeting -->
|
||||||
|
<ContentControl Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
s:View.Model="{Binding TargetSelectionViewModel}"
|
||||||
|
VerticalContentAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
IsTabStop="False" />
|
||||||
|
|
||||||
|
<!-- Operator -->
|
||||||
|
<Button Grid.Row="0"
|
||||||
|
Grid.Column="2"
|
||||||
|
Style="{StaticResource DataModelConditionButtonLeftClickMenu}"
|
||||||
|
Background="#7B7B7B"
|
||||||
|
BorderBrush="#7B7B7B"
|
||||||
|
Content="{Binding SelectedListOperator}"
|
||||||
|
Click="PropertyButton_OnClick"
|
||||||
|
HorizontalAlignment="Left">
|
||||||
|
<Button.ContextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<MenuItem Header="Any" Command="{s:Action SelectListOperator}" CommandParameter="Any" />
|
||||||
|
<MenuItem Header="All" Command="{s:Action SelectListOperator}" CommandParameter="All" />
|
||||||
|
<MenuItem Header="None" Command="{s:Action SelectListOperator}" CommandParameter="None" />
|
||||||
|
<MenuItem Header="Count (NYI)" Command="{s:Action SelectListOperator}" CommandParameter="Count" IsEnabled="False" />
|
||||||
|
</ContextMenu>
|
||||||
|
</Button.ContextMenu>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" Margin="0 4 0 0">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<materialDesign:TransitioningContent>
|
||||||
|
<materialDesign:TransitioningContent.OpeningEffects>
|
||||||
|
<materialDesign:TransitionEffect Kind="FadeIn" />
|
||||||
|
<materialDesign:TransitionEffect Kind="SlideInFromLeft" />
|
||||||
|
</materialDesign:TransitioningContent.OpeningEffects>
|
||||||
|
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
|
||||||
|
</materialDesign:TransitioningContent>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@ -1,14 +1,14 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for DisplayConditionListView.xaml
|
/// Interaction logic for DataModelConditionListView.xaml
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class DisplayConditionListView : UserControl
|
public partial class DataModelConditionListView : UserControl
|
||||||
{
|
{
|
||||||
public DisplayConditionListView()
|
public DataModelConditionListView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
@ -0,0 +1,139 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.UI.Ninject.Factories;
|
||||||
|
using Artemis.UI.Screens.ProfileEditor.Conditions.Abstract;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Input;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Humanizer;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||||
|
{
|
||||||
|
public class DataModelConditionListViewModel : DataModelConditionViewModel, IDisposable
|
||||||
|
{
|
||||||
|
private readonly IDataModelConditionsVmFactory _dataModelConditionsVmFactory;
|
||||||
|
private readonly IDataModelUIService _dataModelUIService;
|
||||||
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
|
private DataModelDynamicViewModel _targetSelectionViewModel;
|
||||||
|
|
||||||
|
public DataModelConditionListViewModel(
|
||||||
|
DataModelConditionList dataModelConditionList,
|
||||||
|
IProfileEditorService profileEditorService,
|
||||||
|
IDataModelUIService dataModelUIService,
|
||||||
|
IDataModelConditionsVmFactory dataModelConditionsVmFactory) : base(dataModelConditionList)
|
||||||
|
{
|
||||||
|
_profileEditorService = profileEditorService;
|
||||||
|
_dataModelUIService = dataModelUIService;
|
||||||
|
_dataModelConditionsVmFactory = dataModelConditionsVmFactory;
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelDynamicViewModel TargetSelectionViewModel
|
||||||
|
{
|
||||||
|
get => _targetSelectionViewModel;
|
||||||
|
set => SetAndNotify(ref _targetSelectionViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelConditionList DataModelConditionList => (DataModelConditionList) Model;
|
||||||
|
|
||||||
|
public string SelectedListOperator => DataModelConditionList.ListOperator.Humanize();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
TargetSelectionViewModel.Dispose();
|
||||||
|
TargetSelectionViewModel.PropertySelected -= TargetSelectionViewModelOnPropertySelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectListOperator(string type)
|
||||||
|
{
|
||||||
|
var enumValue = Enum.Parse<ListOperator>(type);
|
||||||
|
DataModelConditionList.ListOperator = enumValue;
|
||||||
|
NotifyOfPropertyChange(nameof(SelectedListOperator));
|
||||||
|
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCondition(string type)
|
||||||
|
{
|
||||||
|
if (type == "Static")
|
||||||
|
DataModelConditionList.AddChild(new DataModelConditionPredicate(DataModelConditionList, ProfileRightSideType.Static));
|
||||||
|
else if (type == "Dynamic")
|
||||||
|
DataModelConditionList.AddChild(new DataModelConditionPredicate(DataModelConditionList, ProfileRightSideType.Dynamic));
|
||||||
|
|
||||||
|
Update();
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddGroup()
|
||||||
|
{
|
||||||
|
DataModelConditionList.AddChild(new DataModelConditionGroup(DataModelConditionList));
|
||||||
|
|
||||||
|
Update();
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Delete()
|
||||||
|
{
|
||||||
|
base.Delete();
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
TargetSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
||||||
|
TargetSelectionViewModel.FilterTypes = new[] {typeof(IList)};
|
||||||
|
TargetSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(71, 108, 188));
|
||||||
|
TargetSelectionViewModel.Placeholder = "Select a list";
|
||||||
|
TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected;
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyList()
|
||||||
|
{
|
||||||
|
DataModelConditionList.UpdateList(
|
||||||
|
TargetSelectionViewModel.SelectedPropertyViewModel.DataModel,
|
||||||
|
TargetSelectionViewModel.SelectedPropertyViewModel.PropertyPath
|
||||||
|
);
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataModelConditionList.ListDataModel, DataModelConditionList.ListPropertyPath);
|
||||||
|
NotifyOfPropertyChange(nameof(SelectedListOperator));
|
||||||
|
|
||||||
|
// Remove VMs of effects no longer applied on the layer
|
||||||
|
var toRemove = Items.Where(c => !DataModelConditionList.Children.Contains(c.Model)).ToList();
|
||||||
|
// Using RemoveRange breaks our lovely animations
|
||||||
|
foreach (var conditionViewModel in toRemove)
|
||||||
|
Items.Remove(conditionViewModel);
|
||||||
|
|
||||||
|
foreach (var childModel in Model.Children)
|
||||||
|
{
|
||||||
|
if (Items.Any(c => c.Model == childModel))
|
||||||
|
continue;
|
||||||
|
if (!(childModel is DataModelConditionGroup dataModelConditionGroup))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var viewModel = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(dataModelConditionGroup, true);
|
||||||
|
viewModel.IsRootGroup = true;
|
||||||
|
Items.Add(viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var childViewModel in Items)
|
||||||
|
childViewModel.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TargetSelectionViewModelOnPropertySelected(object? sender, DataModelInputDynamicEventArgs e)
|
||||||
|
{
|
||||||
|
ApplyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
<UserControl
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
|
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
|
||||||
|
xmlns:conditions="clr-namespace:Artemis.UI.Screens.ProfileEditor.Conditions"
|
||||||
|
x:Class="Artemis.UI.Screens.ProfileEditor.Conditions.DataModelConditionPredicateView"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="450" d:DesignWidth="800"
|
||||||
|
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=False, Type={x:Type conditions:DataModelConditionPredicateViewModel}}">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DataModelConditions.xaml" />
|
||||||
|
<ResourceDictionary>
|
||||||
|
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
||||||
|
</ResourceDictionary>
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Grid Margin="0 3">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
ToolTip="Delete the predicate"
|
||||||
|
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Foreground="#E74C4C"
|
||||||
|
Width="25"
|
||||||
|
Height="25"
|
||||||
|
Command="{s:Action Delete}">
|
||||||
|
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Left side, always a property -->
|
||||||
|
<ContentControl Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
s:View.Model="{Binding LeftSideSelectionViewModel}"
|
||||||
|
VerticalContentAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
IsTabStop="False" />
|
||||||
|
|
||||||
|
<!-- Operator -->
|
||||||
|
<Button Grid.Row="0"
|
||||||
|
Grid.Column="2"
|
||||||
|
Style="{StaticResource DataModelConditionButtonLeftClickMenu}"
|
||||||
|
Background="#7B7B7B"
|
||||||
|
BorderBrush="#7B7B7B"
|
||||||
|
Content="{Binding SelectedOperator.Description}"
|
||||||
|
Click="PropertyButton_OnClick">
|
||||||
|
<Button.ContextMenu>
|
||||||
|
<ContextMenu ItemsSource="{Binding Operators}">
|
||||||
|
<ContextMenu.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<materialDesign:PackIcon Kind="{Binding Icon}" VerticalAlignment="Center" Margin="0 0 15 0" />
|
||||||
|
<TextBlock Text="{Binding Description}" VerticalAlignment="Center" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ContextMenu.ItemTemplate>
|
||||||
|
<ContextMenu.ItemContainerStyle>
|
||||||
|
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
||||||
|
<Setter Property="Command" Value="{Binding Data.SelectOperatorCommand, Source={StaticResource DataContextProxy}}" />
|
||||||
|
<Setter Property="CommandParameter" Value="{Binding}" />
|
||||||
|
<Setter Property="CommandTarget" Value="{Binding}" />
|
||||||
|
</Style>
|
||||||
|
</ContextMenu.ItemContainerStyle>
|
||||||
|
</ContextMenu>
|
||||||
|
</Button.ContextMenu>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<!-- Right side, either a selection or an input -->
|
||||||
|
<ContentControl Grid.Row="0"
|
||||||
|
Grid.Column="3"
|
||||||
|
s:View.Model="{Binding RightSideSelectionViewModel}"
|
||||||
|
VerticalContentAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
IsTabStop="False" />
|
||||||
|
<ContentControl Grid.Row="0"
|
||||||
|
Grid.Column="3"
|
||||||
|
s:View.Model="{Binding RightSideInputViewModel}"
|
||||||
|
VerticalContentAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
IsTabStop="False" />
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@ -1,14 +1,14 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for DisplayConditionPredicateView.xaml
|
/// Interaction logic for DataModelConditionPredicateView.xaml
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class DisplayConditionPredicateView : UserControl
|
public partial class DataModelConditionPredicateView : UserControl
|
||||||
{
|
{
|
||||||
public DisplayConditionPredicateView()
|
public DataModelConditionPredicateView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
@ -0,0 +1,248 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.Screens.ProfileEditor.Conditions.Abstract;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Input;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Stylet;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||||
|
{
|
||||||
|
public class DataModelConditionPredicateViewModel : DataModelConditionViewModel, IDisposable
|
||||||
|
{
|
||||||
|
private readonly IConditionOperatorService _conditionOperatorService;
|
||||||
|
private readonly IDataModelUIService _dataModelUIService;
|
||||||
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
|
private DataModelDynamicViewModel _leftSideSelectionViewModel;
|
||||||
|
private BindableCollection<ConditionOperator> _operators;
|
||||||
|
private DataModelStaticViewModel _rightSideInputViewModel;
|
||||||
|
private DataModelDynamicViewModel _rightSideSelectionViewModel;
|
||||||
|
private ConditionOperator _selectedOperator;
|
||||||
|
|
||||||
|
private List<Type> _supportedInputTypes;
|
||||||
|
|
||||||
|
public DataModelConditionPredicateViewModel(
|
||||||
|
DataModelConditionPredicate dataModelConditionPredicate,
|
||||||
|
IProfileEditorService profileEditorService,
|
||||||
|
IDataModelUIService dataModelUIService,
|
||||||
|
IConditionOperatorService conditionOperatorService,
|
||||||
|
ISettingsService settingsService) : base(dataModelConditionPredicate)
|
||||||
|
{
|
||||||
|
_profileEditorService = profileEditorService;
|
||||||
|
_dataModelUIService = dataModelUIService;
|
||||||
|
_conditionOperatorService = conditionOperatorService;
|
||||||
|
_supportedInputTypes = new List<Type>();
|
||||||
|
|
||||||
|
SelectOperatorCommand = new DelegateCommand(ExecuteSelectOperatorCommand);
|
||||||
|
Operators = new BindableCollection<ConditionOperator>();
|
||||||
|
|
||||||
|
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
|
||||||
|
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelConditionPredicate DataModelConditionPredicate => (DataModelConditionPredicate) Model;
|
||||||
|
public PluginSetting<bool> ShowDataModelValues { get; }
|
||||||
|
|
||||||
|
|
||||||
|
public BindableCollection<ConditionOperator> Operators
|
||||||
|
{
|
||||||
|
get => _operators;
|
||||||
|
set => SetAndNotify(ref _operators, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelDynamicViewModel LeftSideSelectionViewModel
|
||||||
|
{
|
||||||
|
get => _leftSideSelectionViewModel;
|
||||||
|
set => SetAndNotify(ref _leftSideSelectionViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConditionOperator SelectedOperator
|
||||||
|
{
|
||||||
|
get => _selectedOperator;
|
||||||
|
set => SetAndNotify(ref _selectedOperator, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelDynamicViewModel RightSideSelectionViewModel
|
||||||
|
{
|
||||||
|
get => _rightSideSelectionViewModel;
|
||||||
|
set => SetAndNotify(ref _rightSideSelectionViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DataModelStaticViewModel RightSideInputViewModel
|
||||||
|
{
|
||||||
|
get => _rightSideInputViewModel;
|
||||||
|
set => SetAndNotify(ref _rightSideInputViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DelegateCommand SelectOperatorCommand { get; }
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (LeftSideSelectionViewModel != null)
|
||||||
|
{
|
||||||
|
LeftSideSelectionViewModel.PropertySelected -= LeftSideOnPropertySelected;
|
||||||
|
LeftSideSelectionViewModel.Dispose();
|
||||||
|
LeftSideSelectionViewModel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisposeRightSideStatic();
|
||||||
|
DisposeRightSideDynamic();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Delete()
|
||||||
|
{
|
||||||
|
base.Delete();
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
LeftSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
||||||
|
LeftSideSelectionViewModel.PropertySelected += LeftSideOnPropertySelected;
|
||||||
|
// Determine which types are currently supported
|
||||||
|
var editors = _dataModelUIService.RegisteredDataModelEditors;
|
||||||
|
_supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
|
||||||
|
_supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes));
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
|
||||||
|
LeftSideSelectionViewModel.PopulateSelectedPropertyViewModel(
|
||||||
|
DataModelConditionPredicate.LeftDataModel,
|
||||||
|
DataModelConditionPredicate.LeftPropertyPath
|
||||||
|
);
|
||||||
|
var leftSideType = LeftSideSelectionViewModel.SelectedPropertyViewModel?.PropertyInfo?.PropertyType;
|
||||||
|
|
||||||
|
// Get the supported operators
|
||||||
|
Operators.Clear();
|
||||||
|
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
||||||
|
if (DataModelConditionPredicate.Operator == null)
|
||||||
|
DataModelConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
||||||
|
SelectedOperator = DataModelConditionPredicate.Operator;
|
||||||
|
|
||||||
|
// Ensure the right side has the proper VM
|
||||||
|
var targetType = LeftSideSelectionViewModel?.SelectedPropertyViewModel?.PropertyInfo?.PropertyType;
|
||||||
|
if (DataModelConditionPredicate.PredicateType == ProfileRightSideType.Dynamic)
|
||||||
|
{
|
||||||
|
DisposeRightSideStatic();
|
||||||
|
if (RightSideSelectionViewModel == null)
|
||||||
|
{
|
||||||
|
RightSideSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
||||||
|
RightSideSelectionViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
|
||||||
|
RightSideSelectionViewModel.PropertySelected += RightSideOnPropertySelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
|
||||||
|
DataModelConditionPredicate.RightDataModel,
|
||||||
|
DataModelConditionPredicate.RightPropertyPath
|
||||||
|
);
|
||||||
|
RightSideSelectionViewModel.FilterTypes = new[] {targetType};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DisposeRightSideDynamic();
|
||||||
|
if (RightSideInputViewModel == null)
|
||||||
|
{
|
||||||
|
RightSideInputViewModel = _dataModelUIService.GetStaticInputViewModel(targetType);
|
||||||
|
RightSideInputViewModel.ButtonBrush = (Brush) Application.Current.FindResource("PrimaryHueMidBrush");
|
||||||
|
RightSideInputViewModel.ValueUpdated += RightSideOnValueEntered;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RightSideInputViewModel.TargetType != targetType)
|
||||||
|
RightSideInputViewModel.UpdateTargetType(targetType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyLeftSide()
|
||||||
|
{
|
||||||
|
DataModelConditionPredicate.UpdateLeftSide(
|
||||||
|
LeftSideSelectionViewModel.SelectedPropertyViewModel.DataModel,
|
||||||
|
LeftSideSelectionViewModel.SelectedPropertyViewModel.PropertyPath
|
||||||
|
);
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
SelectedOperator = DataModelConditionPredicate.Operator;
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyRightSideDynamic()
|
||||||
|
{
|
||||||
|
DataModelConditionPredicate.UpdateRightSide(
|
||||||
|
RightSideSelectionViewModel.SelectedPropertyViewModel.DataModel,
|
||||||
|
RightSideSelectionViewModel.SelectedPropertyViewModel.PropertyPath
|
||||||
|
);
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyRightSideStatic(object value)
|
||||||
|
{
|
||||||
|
DataModelConditionPredicate.UpdateRightSide(value);
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyOperator()
|
||||||
|
{
|
||||||
|
DataModelConditionPredicate.UpdateOperator(SelectedOperator);
|
||||||
|
_profileEditorService.UpdateSelectedProfileElement();
|
||||||
|
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LeftSideOnPropertySelected(object sender, DataModelInputDynamicEventArgs e)
|
||||||
|
{
|
||||||
|
ApplyLeftSide();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RightSideOnPropertySelected(object? sender, DataModelInputDynamicEventArgs e)
|
||||||
|
{
|
||||||
|
ApplyRightSideDynamic();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RightSideOnValueEntered(object sender, DataModelInputStaticEventArgs e)
|
||||||
|
{
|
||||||
|
ApplyRightSideStatic(e.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExecuteSelectOperatorCommand(object context)
|
||||||
|
{
|
||||||
|
if (!(context is ConditionOperator DataModelConditionOperator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SelectedOperator = DataModelConditionOperator;
|
||||||
|
ApplyOperator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeRightSideStatic()
|
||||||
|
{
|
||||||
|
if (RightSideInputViewModel != null)
|
||||||
|
{
|
||||||
|
RightSideInputViewModel.ValueUpdated -= RightSideOnValueEntered;
|
||||||
|
RightSideInputViewModel.Dispose();
|
||||||
|
RightSideInputViewModel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeRightSideDynamic()
|
||||||
|
{
|
||||||
|
if (RightSideSelectionViewModel != null)
|
||||||
|
{
|
||||||
|
RightSideSelectionViewModel.PropertySelected -= RightSideOnPropertySelected;
|
||||||
|
RightSideSelectionViewModel.Dispose();
|
||||||
|
RightSideSelectionViewModel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,23 +0,0 @@
|
|||||||
using Artemis.Core;
|
|
||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract
|
|
||||||
{
|
|
||||||
public abstract class DisplayConditionViewModel : Conductor<DisplayConditionViewModel>.Collection.AllActive
|
|
||||||
{
|
|
||||||
protected DisplayConditionViewModel(DataModelConditionPart model)
|
|
||||||
{
|
|
||||||
Model = model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelConditionPart Model { get; }
|
|
||||||
|
|
||||||
public abstract void Update();
|
|
||||||
|
|
||||||
public virtual void Delete()
|
|
||||||
{
|
|
||||||
Model.Parent.RemoveChild(Model);
|
|
||||||
((DisplayConditionViewModel) Parent).Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,186 +0,0 @@
|
|||||||
<UserControl
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
|
||||||
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
|
|
||||||
xmlns:displayConditions="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions"
|
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.DisplayConditionListPredicateView"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=False, Type={x:Type displayConditions:DisplayConditionListPredicateViewModel}}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DisplayConditions.xaml" />
|
|
||||||
<ResourceDictionary>
|
|
||||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
|
||||||
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
|
||||||
<DataTemplate x:Key="DataModelDataTemplate">
|
|
||||||
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
|
|
||||||
<DataTemplate.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
|
|
||||||
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
|
|
||||||
</DataTrigger>
|
|
||||||
</DataTemplate.Triggers>
|
|
||||||
</DataTemplate>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
<Grid Margin="0 3" Visibility="{Binding IsInitialized, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="0"
|
|
||||||
ToolTip="Delete the predicate"
|
|
||||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Foreground="#E74C4C"
|
|
||||||
Width="25"
|
|
||||||
Height="25"
|
|
||||||
Command="{s:Action Delete}">
|
|
||||||
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Left side, always a property -->
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Background="#476CBC"
|
|
||||||
BorderBrush="#476CBC"
|
|
||||||
Style="{StaticResource DisplayConditionButton}"
|
|
||||||
ToolTip="{Binding SelectedLeftSideProperty.DisplayPropertyPath}"
|
|
||||||
Click="PropertyButton_OnClick">
|
|
||||||
<Button.ContextMenu>
|
|
||||||
<ContextMenu ItemsSource="{Binding LeftSideDataModel.Children}" IsOpen="{Binding LeftSideDataModelOpen, Mode=OneWayToSource}">
|
|
||||||
<ContextMenu.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
|
||||||
<Setter Property="ItemsSource" Value="{Binding Children}" />
|
|
||||||
<Setter Property="Command" Value="{Binding Data.SelectLeftPropertyCommand, Source={StaticResource DataContextProxy}}" />
|
|
||||||
<Setter Property="CommandParameter" Value="{Binding}" />
|
|
||||||
<Setter Property="CommandTarget" Value="{Binding}" />
|
|
||||||
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
|
|
||||||
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
|
||||||
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
|
|
||||||
</Style>
|
|
||||||
</ContextMenu.ItemContainerStyle>
|
|
||||||
</ContextMenu>
|
|
||||||
</Button.ContextMenu>
|
|
||||||
<Grid>
|
|
||||||
<TextBlock Text="{Binding SelectedLeftSideProperty.PropertyDescription.Name}"
|
|
||||||
Visibility="{Binding SelectedLeftSideProperty, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
<TextBlock Text="« Select a property »"
|
|
||||||
FontStyle="Italic"
|
|
||||||
Visibility="{Binding SelectedLeftSideProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
|
||||||
</Grid>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Operator -->
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="2"
|
|
||||||
Style="{StaticResource DisplayConditionButtonLeftClickMenu}"
|
|
||||||
Background="#7B7B7B"
|
|
||||||
BorderBrush="#7B7B7B"
|
|
||||||
Content="{Binding SelectedOperator.Description}"
|
|
||||||
Click="PropertyButton_OnClick">
|
|
||||||
<Button.ContextMenu>
|
|
||||||
<ContextMenu ItemsSource="{Binding Operators}">
|
|
||||||
<ContextMenu.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="{Binding Icon}" VerticalAlignment="Center" Margin="0 0 15 0" />
|
|
||||||
<TextBlock Text="{Binding Description}" VerticalAlignment="Center" />
|
|
||||||
</StackPanel>
|
|
||||||
</DataTemplate>
|
|
||||||
</ContextMenu.ItemTemplate>
|
|
||||||
<ContextMenu.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
|
||||||
<Setter Property="Command" Value="{Binding Data.SelectOperatorCommand, Source={StaticResource DataContextProxy}}" />
|
|
||||||
<Setter Property="CommandParameter" Value="{Binding}" />
|
|
||||||
<Setter Property="CommandTarget" Value="{Binding}" />
|
|
||||||
</Style>
|
|
||||||
</ContextMenu.ItemContainerStyle>
|
|
||||||
</ContextMenu>
|
|
||||||
</Button.ContextMenu>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Grid Grid.Row="0"
|
|
||||||
Grid.Column="3"
|
|
||||||
Visibility="{Binding SelectedOperator.SupportsRightSide, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
|
||||||
<!-- Right side property if type is dynamic -->
|
|
||||||
<Button Background="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
BorderBrush="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
Style="{StaticResource DisplayConditionButton}"
|
|
||||||
ToolTip="{Binding SelectedRightSideProperty.DisplayPropertyPath}"
|
|
||||||
Click="PropertyButton_OnClick"
|
|
||||||
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
|
||||||
<Button.ContextMenu>
|
|
||||||
<ContextMenu ItemsSource="{Binding RightSideDataModel.Children}">
|
|
||||||
<ContextMenu.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
|
||||||
<Setter Property="ItemsSource" Value="{Binding Children}" />
|
|
||||||
<Setter Property="Command" Value="{Binding Data.SelectRightPropertyCommand, Source={StaticResource DataContextProxy}}" />
|
|
||||||
<Setter Property="CommandParameter" Value="{Binding}" />
|
|
||||||
<Setter Property="CommandTarget" Value="{Binding}" />
|
|
||||||
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
|
|
||||||
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
|
||||||
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
|
|
||||||
</Style>
|
|
||||||
</ContextMenu.ItemContainerStyle>
|
|
||||||
</ContextMenu>
|
|
||||||
</Button.ContextMenu>
|
|
||||||
<Grid>
|
|
||||||
<TextBlock Text="{Binding SelectedRightSideProperty.PropertyDescription.Name}"
|
|
||||||
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
<TextBlock Text="« Select a property »"
|
|
||||||
FontStyle="Italic"
|
|
||||||
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
|
||||||
</Grid>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Right side property if type is static -->
|
|
||||||
<materialDesign:Transitioner SelectedIndex="{Binding RightSideTransitionIndex}"
|
|
||||||
DefaultTransitionOrigin="0.5, 0.5"
|
|
||||||
Margin="3 -4"
|
|
||||||
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
|
|
||||||
<Button Style="{StaticResource DisplayConditionButton}"
|
|
||||||
Background="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
BorderBrush="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
Margin="0 4"
|
|
||||||
Command="{s:Action ActivateRightSideInputViewModel}"
|
|
||||||
HorizontalAlignment="Left">
|
|
||||||
<Grid>
|
|
||||||
<StackPanel Visibility="{Binding RightStaticValue, Converter={StaticResource NullToVisibilityConverter}}" Orientation="Horizontal">
|
|
||||||
<TextBlock FontWeight="Light"
|
|
||||||
Text="{Binding SelectedLeftSideProperty.PropertyDescription.Prefix}"
|
|
||||||
Visibility="{Binding SelectedLeftSideProperty.PropertyDescription.Prefix, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
<TextBlock Text="{Binding RightStaticValue}" />
|
|
||||||
<TextBlock FontWeight="Light"
|
|
||||||
Text="{Binding SelectedLeftSideProperty.PropertyDescription.Affix}"
|
|
||||||
Visibility="{Binding SelectedLeftSideProperty.PropertyDescription.Affix, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<TextBlock Text="« Enter a value »"
|
|
||||||
FontStyle="Italic"
|
|
||||||
Visibility="{Binding RightStaticValue, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
|
||||||
</Grid>
|
|
||||||
</Button>
|
|
||||||
<Border BorderBrush="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
Background="{DynamicResource MaterialDesignPaper}"
|
|
||||||
CornerRadius="3"
|
|
||||||
Padding="3"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
MinWidth="140">
|
|
||||||
<ContentControl s:View.Model="{Binding RightSideInputViewModel}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
|
|
||||||
</Border>
|
|
||||||
</materialDesign:Transitioner>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,353 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Timers;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.UI.Events;
|
|
||||||
using Artemis.UI.Exceptions;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Artemis.UI.Utilities;
|
|
||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|
||||||
{
|
|
||||||
public class DisplayConditionListPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>, IDisposable
|
|
||||||
{
|
|
||||||
private readonly IConditionOperatorService _conditionOperatorService;
|
|
||||||
private readonly IDataModelUIService _dataModelUIService;
|
|
||||||
private readonly IEventAggregator _eventAggregator;
|
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
|
||||||
private readonly Timer _updateTimer;
|
|
||||||
private bool _isInitialized;
|
|
||||||
private DataModelVisualizationViewModel _leftSideDataModel;
|
|
||||||
private BindableCollection<ConditionOperator> _operators;
|
|
||||||
private DataModelVisualizationViewModel _rightSideDataModel;
|
|
||||||
private DataModelInputViewModel _rightSideInputViewModel;
|
|
||||||
private int _rightSideTransitionIndex;
|
|
||||||
private object _rightStaticValue;
|
|
||||||
private DataModelVisualizationViewModel _selectedLeftSideProperty;
|
|
||||||
private ConditionOperator _selectedOperator;
|
|
||||||
private DataModelVisualizationViewModel _selectedRightSideProperty;
|
|
||||||
|
|
||||||
private List<Type> _supportedInputTypes;
|
|
||||||
|
|
||||||
public DisplayConditionListPredicateViewModel(
|
|
||||||
DataModelConditionListPredicate dataModelConditionListPredicate,
|
|
||||||
IProfileEditorService profileEditorService,
|
|
||||||
IDataModelUIService dataModelUIService,
|
|
||||||
IConditionOperatorService conditionOperatorService,
|
|
||||||
ISettingsService settingsService,
|
|
||||||
IEventAggregator eventAggregator) : base(dataModelConditionListPredicate)
|
|
||||||
{
|
|
||||||
_profileEditorService = profileEditorService;
|
|
||||||
_dataModelUIService = dataModelUIService;
|
|
||||||
_conditionOperatorService = conditionOperatorService;
|
|
||||||
_eventAggregator = eventAggregator;
|
|
||||||
_updateTimer = new Timer(500);
|
|
||||||
_supportedInputTypes = new List<Type>();
|
|
||||||
|
|
||||||
SelectLeftPropertyCommand = new DelegateCommand(ExecuteSelectLeftProperty);
|
|
||||||
SelectRightPropertyCommand = new DelegateCommand(ExecuteSelectRightProperty);
|
|
||||||
SelectOperatorCommand = new DelegateCommand(ExecuteSelectOperatorCommand);
|
|
||||||
Operators = new BindableCollection<ConditionOperator>();
|
|
||||||
|
|
||||||
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
|
|
||||||
|
|
||||||
// Initialize async, no need to wait for it
|
|
||||||
Task.Run(Initialize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelConditionListPredicate DataModelConditionListPredicate => (DataModelConditionListPredicate) Model;
|
|
||||||
public bool ShowRightSidePropertySelection => DataModelConditionListPredicate.PredicateType == ProfileRightSideType.Dynamic;
|
|
||||||
public bool CanActivateRightSideInputViewModel => SelectedLeftSideProperty?.PropertyInfo != null;
|
|
||||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
|
||||||
|
|
||||||
public bool IsInitialized
|
|
||||||
{
|
|
||||||
get => _isInitialized;
|
|
||||||
private set => SetAndNotify(ref _isInitialized, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool LeftSideDataModelOpen { get; set; }
|
|
||||||
|
|
||||||
public DataModelVisualizationViewModel LeftSideDataModel
|
|
||||||
{
|
|
||||||
get => _leftSideDataModel;
|
|
||||||
set => SetAndNotify(ref _leftSideDataModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelVisualizationViewModel RightSideDataModel
|
|
||||||
{
|
|
||||||
get => _rightSideDataModel;
|
|
||||||
set => SetAndNotify(ref _rightSideDataModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RightSideDataModelOpen { get; set; }
|
|
||||||
|
|
||||||
public DataModelVisualizationViewModel SelectedLeftSideProperty
|
|
||||||
{
|
|
||||||
get => _selectedLeftSideProperty;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (!SetAndNotify(ref _selectedLeftSideProperty, value)) return;
|
|
||||||
NotifyOfPropertyChange(nameof(CanActivateRightSideInputViewModel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelVisualizationViewModel SelectedRightSideProperty
|
|
||||||
{
|
|
||||||
get => _selectedRightSideProperty;
|
|
||||||
set => SetAndNotify(ref _selectedRightSideProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object RightStaticValue
|
|
||||||
{
|
|
||||||
get => _rightStaticValue;
|
|
||||||
set => SetAndNotify(ref _rightStaticValue, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RightSideTransitionIndex
|
|
||||||
{
|
|
||||||
get => _rightSideTransitionIndex;
|
|
||||||
set => SetAndNotify(ref _rightSideTransitionIndex, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelInputViewModel RightSideInputViewModel
|
|
||||||
{
|
|
||||||
get => _rightSideInputViewModel;
|
|
||||||
set => SetAndNotify(ref _rightSideInputViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BindableCollection<ConditionOperator> Operators
|
|
||||||
{
|
|
||||||
get => _operators;
|
|
||||||
set => SetAndNotify(ref _operators, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConditionOperator SelectedOperator
|
|
||||||
{
|
|
||||||
get => _selectedOperator;
|
|
||||||
set => SetAndNotify(ref _selectedOperator, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DelegateCommand SelectLeftPropertyCommand { get; }
|
|
||||||
public DelegateCommand SelectRightPropertyCommand { get; }
|
|
||||||
public DelegateCommand SelectOperatorCommand { get; }
|
|
||||||
|
|
||||||
public void Handle(MainWindowKeyEvent message)
|
|
||||||
{
|
|
||||||
if (RightSideInputViewModel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!message.KeyDown && message.EventArgs.Key == Key.Escape)
|
|
||||||
RightSideInputViewModel.Cancel();
|
|
||||||
if (!message.KeyDown && message.EventArgs.Key == Key.Enter)
|
|
||||||
RightSideInputViewModel.Submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Handle(MainWindowMouseEvent message)
|
|
||||||
{
|
|
||||||
if (RightSideInputViewModel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (message.Sender is FrameworkElement frameworkElement && !frameworkElement.IsDescendantOf(RightSideInputViewModel.View))
|
|
||||||
RightSideInputViewModel.Submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Delete()
|
|
||||||
{
|
|
||||||
base.Delete();
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Initialize()
|
|
||||||
{
|
|
||||||
// Get the data models
|
|
||||||
LeftSideDataModel = GetListDataModel();
|
|
||||||
RightSideDataModel = GetListDataModel();
|
|
||||||
LeftSideDataModel.UpdateRequested += LeftDataModelUpdateRequested;
|
|
||||||
RightSideDataModel.UpdateRequested += RightDataModelUpdateRequested;
|
|
||||||
|
|
||||||
// Determine which types are currently supported
|
|
||||||
var editors = _dataModelUIService.RegisteredDataModelEditors;
|
|
||||||
_supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
|
|
||||||
_supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes));
|
|
||||||
|
|
||||||
Update();
|
|
||||||
|
|
||||||
_updateTimer.Start();
|
|
||||||
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
|
|
||||||
|
|
||||||
IsInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
// Not yet initialized if these are null
|
|
||||||
if (LeftSideDataModel == null || RightSideDataModel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var listDataModelGuid = DataModelConditionListPredicate.ListDataModel.PluginInfo.Guid;
|
|
||||||
|
|
||||||
// If static, only allow selecting properties also supported by input
|
|
||||||
if (DataModelConditionListPredicate.PredicateType == ProfileRightSideType.Static)
|
|
||||||
LeftSideDataModel.ApplyTypeFilter(false, _supportedInputTypes.ToArray());
|
|
||||||
|
|
||||||
// Determine the left side property first
|
|
||||||
SelectedLeftSideProperty = LeftSideDataModel.GetChildByPath(listDataModelGuid, DataModelConditionListPredicate.LeftPropertyPath);
|
|
||||||
var leftSideType = SelectedLeftSideProperty?.PropertyInfo?.PropertyType;
|
|
||||||
|
|
||||||
// Get the supported operators
|
|
||||||
Operators.Clear();
|
|
||||||
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
|
||||||
if (DataModelConditionListPredicate.Operator == null)
|
|
||||||
DataModelConditionListPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
|
||||||
SelectedOperator = DataModelConditionListPredicate.Operator;
|
|
||||||
|
|
||||||
// Determine the right side
|
|
||||||
if (DataModelConditionListPredicate.PredicateType == ProfileRightSideType.Dynamic)
|
|
||||||
{
|
|
||||||
SelectedRightSideProperty = RightSideDataModel.GetChildByPath(listDataModelGuid, DataModelConditionListPredicate.RightPropertyPath);
|
|
||||||
RightSideDataModel.ApplyTypeFilter(true, leftSideType);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
RightStaticValue = DataModelConditionListPredicate.RightStaticValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyLeftSide()
|
|
||||||
{
|
|
||||||
DataModelConditionListPredicate.UpdateLeftSide(SelectedLeftSideProperty.PropertyPath);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
SelectedOperator = DataModelConditionListPredicate.Operator;
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyRightSideDynamic()
|
|
||||||
{
|
|
||||||
DataModelConditionListPredicate.UpdateRightSideDynamic(SelectedRightSideProperty.PropertyPath);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyRightSideStatic(object value, bool isSubmitted)
|
|
||||||
{
|
|
||||||
if (isSubmitted)
|
|
||||||
{
|
|
||||||
DataModelConditionListPredicate.UpdateRightSideStatic(value);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
RightSideTransitionIndex = 0;
|
|
||||||
RightSideInputViewModel = null;
|
|
||||||
RightStaticValue = value;
|
|
||||||
_eventAggregator.Unsubscribe(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyOperator()
|
|
||||||
{
|
|
||||||
DataModelConditionListPredicate.UpdateOperator(SelectedOperator);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ActivateRightSideInputViewModel()
|
|
||||||
{
|
|
||||||
if (SelectedLeftSideProperty?.PropertyInfo == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RightSideTransitionIndex = 1;
|
|
||||||
RightSideInputViewModel = _dataModelUIService.GetDataModelInputViewModel(
|
|
||||||
SelectedLeftSideProperty.PropertyInfo.PropertyType,
|
|
||||||
SelectedLeftSideProperty.PropertyDescription,
|
|
||||||
DataModelConditionListPredicate.RightStaticValue,
|
|
||||||
ApplyRightSideStatic
|
|
||||||
);
|
|
||||||
_eventAggregator.Subscribe(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
if (LeftSideDataModelOpen)
|
|
||||||
LeftSideDataModel.Update(_dataModelUIService);
|
|
||||||
else if (RightSideDataModelOpen)
|
|
||||||
RightSideDataModel.Update(_dataModelUIService);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RightDataModelUpdateRequested(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var listDataModelGuid = DataModelConditionListPredicate.ListDataModel.PluginInfo.Guid;
|
|
||||||
var leftSideType = SelectedLeftSideProperty?.PropertyInfo?.PropertyType;
|
|
||||||
|
|
||||||
// If the right side property is missing it may be available now that the data model has been updated
|
|
||||||
if (SelectedRightSideProperty == null && DataModelConditionListPredicate.RightPropertyPath != null)
|
|
||||||
SelectedRightSideProperty = RightSideDataModel.GetChildByPath(listDataModelGuid, DataModelConditionListPredicate.RightPropertyPath);
|
|
||||||
|
|
||||||
// With the data model updated, also reapply the filter
|
|
||||||
RightSideDataModel.ApplyTypeFilter(true, leftSideType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LeftDataModelUpdateRequested(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (DataModelConditionListPredicate.PredicateType == ProfileRightSideType.Static)
|
|
||||||
LeftSideDataModel.ApplyTypeFilter(false, _supportedInputTypes.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataModelVisualizationViewModel GetListDataModel()
|
|
||||||
{
|
|
||||||
if (DataModelConditionListPredicate.ListDataModel == null || DataModelConditionListPredicate.ListPropertyPath == null)
|
|
||||||
throw new ArtemisUIException("Cannot create a list predicate without first selecting a target list");
|
|
||||||
|
|
||||||
var dataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
|
||||||
var listDataModel = (DataModelListViewModel) dataModel.GetChildByPath(
|
|
||||||
DataModelConditionListPredicate.ListDataModel.PluginInfo.Guid,
|
|
||||||
DataModelConditionListPredicate.ListPropertyPath
|
|
||||||
);
|
|
||||||
|
|
||||||
return listDataModel.GetListTypeViewModel(_dataModelUIService);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSelectLeftProperty(object context)
|
|
||||||
{
|
|
||||||
if (!(context is DataModelVisualizationViewModel dataModelVisualizationViewModel))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SelectedLeftSideProperty = dataModelVisualizationViewModel;
|
|
||||||
ApplyLeftSide();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSelectRightProperty(object context)
|
|
||||||
{
|
|
||||||
if (!(context is DataModelVisualizationViewModel dataModelVisualizationViewModel))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SelectedRightSideProperty = dataModelVisualizationViewModel;
|
|
||||||
ApplyRightSideDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSelectOperatorCommand(object context)
|
|
||||||
{
|
|
||||||
if (!(context is ConditionOperator displayConditionOperator))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SelectedOperator = displayConditionOperator;
|
|
||||||
ApplyOperator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_updateTimer.Dispose();
|
|
||||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.DisplayConditionListView"
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions"
|
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
|
||||||
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance Type=local:DisplayConditionListViewModel, IsDesignTimeCreatable=False}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DisplayConditions.xaml" />
|
|
||||||
<ResourceDictionary>
|
|
||||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
|
||||||
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
|
||||||
<DataTemplate x:Key="DataModelDataTemplate">
|
|
||||||
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
|
|
||||||
<DataTemplate.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
|
|
||||||
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
|
|
||||||
</DataTrigger>
|
|
||||||
</DataTemplate.Triggers>
|
|
||||||
</DataTemplate>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
<Grid Margin="0 3">
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto" />
|
|
||||||
<RowDefinition Height="*" />
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="0"
|
|
||||||
ToolTip="Delete the list predicate and all its children"
|
|
||||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Foreground="#E74C4C"
|
|
||||||
Width="25"
|
|
||||||
Height="25"
|
|
||||||
Command="{s:Action Delete}">
|
|
||||||
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Left side, the list this predicate is targeting -->
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Background="#476CBC"
|
|
||||||
BorderBrush="#476CBC"
|
|
||||||
Style="{StaticResource DisplayConditionButton}"
|
|
||||||
ToolTip="{Binding SelectedListProperty.DisplayPropertyPath}"
|
|
||||||
Click="PropertyButton_OnClick"
|
|
||||||
Visibility="{Binding IsInitialized, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
|
||||||
<Button.ContextMenu>
|
|
||||||
<ContextMenu ItemsSource="{Binding TargetDataModel.Children}" IsOpen="{Binding TargetDataModelOpen, Mode=OneWayToSource}">
|
|
||||||
<ContextMenu.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
|
||||||
<Setter Property="ItemsSource" Value="{Binding Children}" />
|
|
||||||
<Setter Property="Command" Value="{Binding Data.SelectListPropertyCommand, Source={StaticResource DataContextProxy}}" />
|
|
||||||
<Setter Property="CommandParameter" Value="{Binding}" />
|
|
||||||
<Setter Property="CommandTarget" Value="{Binding}" />
|
|
||||||
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
|
|
||||||
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
|
||||||
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
|
|
||||||
</Style>
|
|
||||||
</ContextMenu.ItemContainerStyle>
|
|
||||||
</ContextMenu>
|
|
||||||
</Button.ContextMenu>
|
|
||||||
<Grid>
|
|
||||||
<TextBlock Text="{Binding SelectedListProperty.PropertyDescription.Name}"
|
|
||||||
Visibility="{Binding SelectedListProperty, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
<TextBlock Text="« Select a list »"
|
|
||||||
FontStyle="Italic"
|
|
||||||
Visibility="{Binding SelectedListProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
|
||||||
</Grid>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Operator -->
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="2"
|
|
||||||
Style="{StaticResource DisplayConditionButtonLeftClickMenu}"
|
|
||||||
Background="#7B7B7B"
|
|
||||||
BorderBrush="#7B7B7B"
|
|
||||||
Content="{Binding SelectedListOperator}"
|
|
||||||
Click="PropertyButton_OnClick"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Visibility="{Binding IsInitialized, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
|
||||||
<Button.ContextMenu>
|
|
||||||
<ContextMenu>
|
|
||||||
<MenuItem Header="Any" Command="{s:Action SelectListOperator}" CommandParameter="Any" />
|
|
||||||
<MenuItem Header="All" Command="{s:Action SelectListOperator}" CommandParameter="All" />
|
|
||||||
<MenuItem Header="None" Command="{s:Action SelectListOperator}" CommandParameter="None" />
|
|
||||||
<MenuItem Header="Count (NYI)" Command="{s:Action SelectListOperator}" CommandParameter="Count" IsEnabled="False" />
|
|
||||||
</ContextMenu>
|
|
||||||
</Button.ContextMenu>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" Margin="0 4 0 0">
|
|
||||||
<ItemsControl.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<materialDesign:TransitioningContent>
|
|
||||||
<materialDesign:TransitioningContent.OpeningEffects>
|
|
||||||
<materialDesign:TransitionEffect Kind="FadeIn" />
|
|
||||||
<materialDesign:TransitionEffect Kind="SlideInFromLeft" />
|
|
||||||
</materialDesign:TransitioningContent.OpeningEffects>
|
|
||||||
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
|
|
||||||
</materialDesign:TransitioningContent>
|
|
||||||
</DataTemplate>
|
|
||||||
</ItemsControl.ItemTemplate>
|
|
||||||
</ItemsControl>
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,203 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Timers;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.UI.Ninject.Factories;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Artemis.UI.Utilities;
|
|
||||||
using Humanizer;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|
||||||
{
|
|
||||||
public class DisplayConditionListViewModel : DisplayConditionViewModel, IDisposable
|
|
||||||
{
|
|
||||||
private readonly IDataModelUIService _dataModelUIService;
|
|
||||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
|
||||||
private readonly Timer _updateTimer;
|
|
||||||
private bool _isInitialized;
|
|
||||||
private DataModelListViewModel _selectedListProperty;
|
|
||||||
private DataModelPropertiesViewModel _targetDataModel;
|
|
||||||
|
|
||||||
public DisplayConditionListViewModel(
|
|
||||||
DataModelConditionList dataModelConditionList,
|
|
||||||
DisplayConditionViewModel parent,
|
|
||||||
IProfileEditorService profileEditorService,
|
|
||||||
IDataModelUIService dataModelUIService,
|
|
||||||
IDisplayConditionsVmFactory displayConditionsVmFactory,
|
|
||||||
ISettingsService settingsService) : base(dataModelConditionList)
|
|
||||||
{
|
|
||||||
_profileEditorService = profileEditorService;
|
|
||||||
_dataModelUIService = dataModelUIService;
|
|
||||||
_displayConditionsVmFactory = displayConditionsVmFactory;
|
|
||||||
_updateTimer = new Timer(500);
|
|
||||||
|
|
||||||
SelectListPropertyCommand = new DelegateCommand(ExecuteSelectListProperty);
|
|
||||||
|
|
||||||
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
|
|
||||||
|
|
||||||
// Initialize async, no need to wait for it
|
|
||||||
Task.Run(Initialize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DelegateCommand SelectListPropertyCommand { get; }
|
|
||||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
|
||||||
|
|
||||||
public DataModelConditionList DataModelConditionList => (DataModelConditionList) Model;
|
|
||||||
|
|
||||||
public bool IsInitialized
|
|
||||||
{
|
|
||||||
get => _isInitialized;
|
|
||||||
set => SetAndNotify(ref _isInitialized, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TargetDataModelOpen { get; set; }
|
|
||||||
|
|
||||||
public DataModelPropertiesViewModel TargetDataModel
|
|
||||||
{
|
|
||||||
get => _targetDataModel;
|
|
||||||
set => SetAndNotify(ref _targetDataModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelListViewModel SelectedListProperty
|
|
||||||
{
|
|
||||||
get => _selectedListProperty;
|
|
||||||
set => SetAndNotify(ref _selectedListProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string SelectedListOperator => DataModelConditionList.ListOperator.Humanize();
|
|
||||||
|
|
||||||
public void SelectListOperator(string type)
|
|
||||||
{
|
|
||||||
var enumValue = Enum.Parse<ListOperator>(type);
|
|
||||||
DataModelConditionList.ListOperator = enumValue;
|
|
||||||
NotifyOfPropertyChange(nameof(SelectedListOperator));
|
|
||||||
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddCondition(string type)
|
|
||||||
{
|
|
||||||
if (type == "Static")
|
|
||||||
DataModelConditionList.AddChild(new DataModelConditionPredicate(DataModelConditionList, ProfileRightSideType.Static));
|
|
||||||
else if (type == "Dynamic")
|
|
||||||
DataModelConditionList.AddChild(new DataModelConditionPredicate(DataModelConditionList, ProfileRightSideType.Dynamic));
|
|
||||||
|
|
||||||
Update();
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddGroup()
|
|
||||||
{
|
|
||||||
DataModelConditionList.AddChild(new DataModelConditionGroup(DataModelConditionList));
|
|
||||||
|
|
||||||
Update();
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Delete()
|
|
||||||
{
|
|
||||||
base.Delete();
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Initialize()
|
|
||||||
{
|
|
||||||
// Get the data models
|
|
||||||
TargetDataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
|
||||||
TargetDataModel.UpdateRequested += TargetDataModelUpdateRequested;
|
|
||||||
|
|
||||||
Update();
|
|
||||||
|
|
||||||
_updateTimer.Start();
|
|
||||||
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
|
|
||||||
|
|
||||||
IsInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyList()
|
|
||||||
{
|
|
||||||
DataModelConditionList.UpdateList(SelectedListProperty.DataModel, SelectedListProperty.PropertyPath);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
if (TargetDataModel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
NotifyOfPropertyChange(nameof(SelectedListOperator));
|
|
||||||
|
|
||||||
// Update the selected list property
|
|
||||||
if (DataModelConditionList.ListDataModel != null && DataModelConditionList.ListPropertyPath != null)
|
|
||||||
{
|
|
||||||
var child = TargetDataModel.GetChildByPath(
|
|
||||||
DataModelConditionList.ListDataModel.PluginInfo.Guid,
|
|
||||||
DataModelConditionList.ListPropertyPath
|
|
||||||
);
|
|
||||||
SelectedListProperty = child as DataModelListViewModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure filtering is applied to include Enumerables only
|
|
||||||
TargetDataModel.ApplyTypeFilter(true, typeof(IList));
|
|
||||||
|
|
||||||
// Remove VMs of effects no longer applied on the layer
|
|
||||||
var toRemove = Items.Where(c => !DataModelConditionList.Children.Contains(c.Model)).ToList();
|
|
||||||
// Using RemoveRange breaks our lovely animations
|
|
||||||
foreach (var displayConditionViewModel in toRemove)
|
|
||||||
Items.Remove(displayConditionViewModel);
|
|
||||||
|
|
||||||
foreach (var childModel in Model.Children)
|
|
||||||
{
|
|
||||||
if (Items.Any(c => c.Model == childModel))
|
|
||||||
continue;
|
|
||||||
if (!(childModel is DataModelConditionGroup displayConditionGroup))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, true);
|
|
||||||
viewModel.IsRootGroup = true;
|
|
||||||
Items.Add(viewModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var childViewModel in Items)
|
|
||||||
childViewModel.Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
if (TargetDataModelOpen)
|
|
||||||
{
|
|
||||||
TargetDataModel?.Update(_dataModelUIService);
|
|
||||||
SelectedListProperty?.Update(_dataModelUIService);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TargetDataModelUpdateRequested(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
TargetDataModel.ApplyTypeFilter(true, typeof(IList));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void ExecuteSelectListProperty(object context)
|
|
||||||
{
|
|
||||||
if (!(context is DataModelListViewModel dataModelListViewModel))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SelectedListProperty = dataModelListViewModel;
|
|
||||||
ApplyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_updateTimer.Dispose();
|
|
||||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,186 +0,0 @@
|
|||||||
<UserControl
|
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
|
||||||
xmlns:utilities="clr-namespace:Artemis.UI.Utilities"
|
|
||||||
xmlns:displayConditions="clr-namespace:Artemis.UI.Screens.ProfileEditor.DisplayConditions"
|
|
||||||
x:Class="Artemis.UI.Screens.ProfileEditor.DisplayConditions.DisplayConditionPredicateView"
|
|
||||||
mc:Ignorable="d"
|
|
||||||
d:DesignHeight="450" d:DesignWidth="800"
|
|
||||||
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=False, Type={x:Type displayConditions:DisplayConditionPredicateViewModel}}">
|
|
||||||
<UserControl.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<ResourceDictionary.MergedDictionaries>
|
|
||||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DisplayConditions.xaml" />
|
|
||||||
<ResourceDictionary>
|
|
||||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
|
||||||
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
|
||||||
<DataTemplate x:Key="DataModelDataTemplate">
|
|
||||||
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
|
|
||||||
<DataTemplate.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
|
|
||||||
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
|
|
||||||
</DataTrigger>
|
|
||||||
</DataTemplate.Triggers>
|
|
||||||
</DataTemplate>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</ResourceDictionary.MergedDictionaries>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</UserControl.Resources>
|
|
||||||
<Grid Margin="0 3" Visibility="{Binding IsInitialized, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="0"
|
|
||||||
ToolTip="Delete the predicate"
|
|
||||||
Style="{StaticResource MaterialDesignIconForegroundButton}"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Foreground="#E74C4C"
|
|
||||||
Width="25"
|
|
||||||
Height="25"
|
|
||||||
Command="{s:Action Delete}">
|
|
||||||
<materialDesign:PackIcon Kind="Close" Width="18" Height="18" />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Left side, always a property -->
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="1"
|
|
||||||
Background="#ab47bc"
|
|
||||||
BorderBrush="#ab47bc"
|
|
||||||
Style="{StaticResource DisplayConditionButton}"
|
|
||||||
ToolTip="{Binding SelectedLeftSideProperty.DisplayPropertyPath}"
|
|
||||||
Click="PropertyButton_OnClick">
|
|
||||||
<Button.ContextMenu>
|
|
||||||
<ContextMenu ItemsSource="{Binding LeftSideDataModel.Children}" IsOpen="{Binding LeftSideDataModelOpen, Mode=OneWayToSource}">
|
|
||||||
<ContextMenu.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
|
||||||
<Setter Property="ItemsSource" Value="{Binding Children}" />
|
|
||||||
<Setter Property="Command" Value="{Binding Data.SelectLeftPropertyCommand, Source={StaticResource DataContextProxy}}" />
|
|
||||||
<Setter Property="CommandParameter" Value="{Binding}" />
|
|
||||||
<Setter Property="CommandTarget" Value="{Binding}" />
|
|
||||||
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
|
|
||||||
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
|
||||||
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
|
|
||||||
</Style>
|
|
||||||
</ContextMenu.ItemContainerStyle>
|
|
||||||
</ContextMenu>
|
|
||||||
</Button.ContextMenu>
|
|
||||||
<Grid>
|
|
||||||
<TextBlock Text="{Binding SelectedLeftSideProperty.PropertyDescription.Name}"
|
|
||||||
Visibility="{Binding SelectedLeftSideProperty, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
<TextBlock Text="« Select a property »"
|
|
||||||
FontStyle="Italic"
|
|
||||||
Visibility="{Binding SelectedLeftSideProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
|
||||||
</Grid>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Operator -->
|
|
||||||
<Button Grid.Row="0"
|
|
||||||
Grid.Column="2"
|
|
||||||
Style="{StaticResource DisplayConditionButtonLeftClickMenu}"
|
|
||||||
Background="#7B7B7B"
|
|
||||||
BorderBrush="#7B7B7B"
|
|
||||||
Content="{Binding SelectedOperator.Description}"
|
|
||||||
Click="PropertyButton_OnClick">
|
|
||||||
<Button.ContextMenu>
|
|
||||||
<ContextMenu ItemsSource="{Binding Operators}">
|
|
||||||
<ContextMenu.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<materialDesign:PackIcon Kind="{Binding Icon}" VerticalAlignment="Center" Margin="0 0 15 0" />
|
|
||||||
<TextBlock Text="{Binding Description}" VerticalAlignment="Center" />
|
|
||||||
</StackPanel>
|
|
||||||
</DataTemplate>
|
|
||||||
</ContextMenu.ItemTemplate>
|
|
||||||
<ContextMenu.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
|
||||||
<Setter Property="Command" Value="{Binding Data.SelectOperatorCommand, Source={StaticResource DataContextProxy}}" />
|
|
||||||
<Setter Property="CommandParameter" Value="{Binding}" />
|
|
||||||
<Setter Property="CommandTarget" Value="{Binding}" />
|
|
||||||
</Style>
|
|
||||||
</ContextMenu.ItemContainerStyle>
|
|
||||||
</ContextMenu>
|
|
||||||
</Button.ContextMenu>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Grid Grid.Row="0"
|
|
||||||
Grid.Column="3"
|
|
||||||
Visibility="{Binding SelectedOperator.SupportsRightSide, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
|
||||||
<!-- Right side property if type is dynamic -->
|
|
||||||
<Button Background="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
BorderBrush="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
Style="{StaticResource DisplayConditionButton}"
|
|
||||||
ToolTip="{Binding SelectedRightSideProperty.DisplayPropertyPath}"
|
|
||||||
Click="PropertyButton_OnClick"
|
|
||||||
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}">
|
|
||||||
<Button.ContextMenu>
|
|
||||||
<ContextMenu ItemsSource="{Binding RightSideDataModel.Children}">
|
|
||||||
<ContextMenu.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
|
|
||||||
<Setter Property="ItemsSource" Value="{Binding Children}" />
|
|
||||||
<Setter Property="Command" Value="{Binding Data.SelectRightPropertyCommand, Source={StaticResource DataContextProxy}}" />
|
|
||||||
<Setter Property="CommandParameter" Value="{Binding}" />
|
|
||||||
<Setter Property="CommandTarget" Value="{Binding}" />
|
|
||||||
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
|
|
||||||
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
|
|
||||||
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
|
|
||||||
</Style>
|
|
||||||
</ContextMenu.ItemContainerStyle>
|
|
||||||
</ContextMenu>
|
|
||||||
</Button.ContextMenu>
|
|
||||||
<Grid>
|
|
||||||
<TextBlock Text="{Binding SelectedRightSideProperty.PropertyDescription.Name}"
|
|
||||||
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
<TextBlock Text="« Select a property »"
|
|
||||||
FontStyle="Italic"
|
|
||||||
Visibility="{Binding SelectedRightSideProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
|
||||||
</Grid>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<!-- Right side property if type is static -->
|
|
||||||
<materialDesign:Transitioner SelectedIndex="{Binding RightSideTransitionIndex}"
|
|
||||||
DefaultTransitionOrigin="0.5, 0.5"
|
|
||||||
Margin="3 -4"
|
|
||||||
Visibility="{Binding ShowRightSidePropertySelection, Converter={x:Static s:BoolToVisibilityConverter.InverseInstance}, Mode=OneWay}">
|
|
||||||
<Button Style="{StaticResource DisplayConditionButton}"
|
|
||||||
Background="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
BorderBrush="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
Margin="0 4"
|
|
||||||
Command="{s:Action ActivateRightSideInputViewModel}"
|
|
||||||
HorizontalAlignment="Left">
|
|
||||||
<Grid>
|
|
||||||
<StackPanel Visibility="{Binding RightStaticValue, Converter={StaticResource NullToVisibilityConverter}}" Orientation="Horizontal">
|
|
||||||
<TextBlock FontWeight="Light"
|
|
||||||
Text="{Binding SelectedLeftSideProperty.PropertyDescription.Prefix}"
|
|
||||||
Visibility="{Binding SelectedLeftSideProperty.PropertyDescription.Prefix, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
<TextBlock Text="{Binding RightStaticValue}" />
|
|
||||||
<TextBlock FontWeight="Light"
|
|
||||||
Text="{Binding SelectedLeftSideProperty.PropertyDescription.Affix}"
|
|
||||||
Visibility="{Binding SelectedLeftSideProperty.PropertyDescription.Affix, Converter={StaticResource NullToVisibilityConverter}}" />
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<TextBlock Text="« Enter a value »"
|
|
||||||
FontStyle="Italic"
|
|
||||||
Visibility="{Binding RightStaticValue, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
|
|
||||||
</Grid>
|
|
||||||
</Button>
|
|
||||||
<Border BorderBrush="{DynamicResource PrimaryHueMidBrush}"
|
|
||||||
Background="{DynamicResource MaterialDesignPaper}"
|
|
||||||
CornerRadius="3"
|
|
||||||
Padding="3"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
MinWidth="140">
|
|
||||||
<ContentControl s:View.Model="{Binding RightSideInputViewModel}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
|
|
||||||
</Border>
|
|
||||||
</materialDesign:Transitioner>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</UserControl>
|
|
||||||
@ -1,332 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Timers;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.Core.Services;
|
|
||||||
using Artemis.UI.Events;
|
|
||||||
using Artemis.UI.Screens.ProfileEditor.DisplayConditions.Abstract;
|
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using Artemis.UI.Shared.Services;
|
|
||||||
using Artemis.UI.Utilities;
|
|
||||||
using Stylet;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|
||||||
{
|
|
||||||
public class DisplayConditionPredicateViewModel : DisplayConditionViewModel, IHandle<MainWindowKeyEvent>, IHandle<MainWindowMouseEvent>, IDisposable
|
|
||||||
{
|
|
||||||
private readonly IConditionOperatorService _conditionOperatorService;
|
|
||||||
private readonly IDataModelUIService _dataModelUIService;
|
|
||||||
private readonly IEventAggregator _eventAggregator;
|
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
|
||||||
private readonly Timer _updateTimer;
|
|
||||||
private bool _isInitialized;
|
|
||||||
private DataModelPropertiesViewModel _leftSideDataModel;
|
|
||||||
private BindableCollection<ConditionOperator> _operators;
|
|
||||||
private DataModelPropertiesViewModel _rightSideDataModel;
|
|
||||||
private DataModelInputViewModel _rightSideInputViewModel;
|
|
||||||
private int _rightSideTransitionIndex;
|
|
||||||
private object _rightStaticValue;
|
|
||||||
private DataModelVisualizationViewModel _selectedLeftSideProperty;
|
|
||||||
private ConditionOperator _selectedOperator;
|
|
||||||
private DataModelVisualizationViewModel _selectedRightSideProperty;
|
|
||||||
|
|
||||||
private List<Type> _supportedInputTypes;
|
|
||||||
|
|
||||||
public DisplayConditionPredicateViewModel(
|
|
||||||
DataModelConditionPredicate dataModelConditionPredicate,
|
|
||||||
IProfileEditorService profileEditorService,
|
|
||||||
IDataModelUIService dataModelUIService,
|
|
||||||
IConditionOperatorService conditionOperatorService,
|
|
||||||
ISettingsService settingsService,
|
|
||||||
IEventAggregator eventAggregator) : base(dataModelConditionPredicate)
|
|
||||||
{
|
|
||||||
_profileEditorService = profileEditorService;
|
|
||||||
_dataModelUIService = dataModelUIService;
|
|
||||||
_conditionOperatorService = conditionOperatorService;
|
|
||||||
_eventAggregator = eventAggregator;
|
|
||||||
_updateTimer = new Timer(500);
|
|
||||||
_supportedInputTypes = new List<Type>();
|
|
||||||
|
|
||||||
SelectLeftPropertyCommand = new DelegateCommand(ExecuteSelectLeftProperty);
|
|
||||||
SelectRightPropertyCommand = new DelegateCommand(ExecuteSelectRightProperty);
|
|
||||||
SelectOperatorCommand = new DelegateCommand(ExecuteSelectOperatorCommand);
|
|
||||||
Operators = new BindableCollection<ConditionOperator>();
|
|
||||||
|
|
||||||
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
|
|
||||||
|
|
||||||
Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelConditionPredicate DataModelConditionPredicate => (DataModelConditionPredicate) Model;
|
|
||||||
public bool ShowRightSidePropertySelection => DataModelConditionPredicate.PredicateType == ProfileRightSideType.Dynamic;
|
|
||||||
public bool CanActivateRightSideInputViewModel => SelectedLeftSideProperty?.PropertyInfo != null;
|
|
||||||
public PluginSetting<bool> ShowDataModelValues { get; }
|
|
||||||
|
|
||||||
public bool IsInitialized
|
|
||||||
{
|
|
||||||
get => _isInitialized;
|
|
||||||
private set => SetAndNotify(ref _isInitialized, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool LeftSideDataModelOpen { get; set; }
|
|
||||||
|
|
||||||
public DataModelPropertiesViewModel LeftSideDataModel
|
|
||||||
{
|
|
||||||
get => _leftSideDataModel;
|
|
||||||
set => SetAndNotify(ref _leftSideDataModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelPropertiesViewModel RightSideDataModel
|
|
||||||
{
|
|
||||||
get => _rightSideDataModel;
|
|
||||||
set => SetAndNotify(ref _rightSideDataModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RightSideDataModelOpen { get; set; }
|
|
||||||
|
|
||||||
public DataModelVisualizationViewModel SelectedLeftSideProperty
|
|
||||||
{
|
|
||||||
get => _selectedLeftSideProperty;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (!SetAndNotify(ref _selectedLeftSideProperty, value)) return;
|
|
||||||
NotifyOfPropertyChange(nameof(CanActivateRightSideInputViewModel));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelVisualizationViewModel SelectedRightSideProperty
|
|
||||||
{
|
|
||||||
get => _selectedRightSideProperty;
|
|
||||||
set => SetAndNotify(ref _selectedRightSideProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public object RightStaticValue
|
|
||||||
{
|
|
||||||
get => _rightStaticValue;
|
|
||||||
set => SetAndNotify(ref _rightStaticValue, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RightSideTransitionIndex
|
|
||||||
{
|
|
||||||
get => _rightSideTransitionIndex;
|
|
||||||
set => SetAndNotify(ref _rightSideTransitionIndex, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataModelInputViewModel RightSideInputViewModel
|
|
||||||
{
|
|
||||||
get => _rightSideInputViewModel;
|
|
||||||
set => SetAndNotify(ref _rightSideInputViewModel, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BindableCollection<ConditionOperator> Operators
|
|
||||||
{
|
|
||||||
get => _operators;
|
|
||||||
set => SetAndNotify(ref _operators, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConditionOperator SelectedOperator
|
|
||||||
{
|
|
||||||
get => _selectedOperator;
|
|
||||||
set => SetAndNotify(ref _selectedOperator, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DelegateCommand SelectLeftPropertyCommand { get; }
|
|
||||||
public DelegateCommand SelectRightPropertyCommand { get; }
|
|
||||||
public DelegateCommand SelectOperatorCommand { get; }
|
|
||||||
|
|
||||||
public void Handle(MainWindowKeyEvent message)
|
|
||||||
{
|
|
||||||
if (RightSideInputViewModel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!message.KeyDown && message.EventArgs.Key == Key.Escape)
|
|
||||||
RightSideInputViewModel.Cancel();
|
|
||||||
if (!message.KeyDown && message.EventArgs.Key == Key.Enter)
|
|
||||||
RightSideInputViewModel.Submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Handle(MainWindowMouseEvent message)
|
|
||||||
{
|
|
||||||
if (RightSideInputViewModel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (message.Sender is FrameworkElement frameworkElement && !frameworkElement.IsDescendantOf(RightSideInputViewModel.View))
|
|
||||||
RightSideInputViewModel.Submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Delete()
|
|
||||||
{
|
|
||||||
base.Delete();
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Initialize()
|
|
||||||
{
|
|
||||||
// Get the data models
|
|
||||||
LeftSideDataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
|
||||||
RightSideDataModel = _dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule(), true);
|
|
||||||
|
|
||||||
// Determine which types are currently supported
|
|
||||||
var editors = _dataModelUIService.RegisteredDataModelEditors;
|
|
||||||
_supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
|
|
||||||
_supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes));
|
|
||||||
|
|
||||||
LeftSideDataModel.UpdateRequested += LeftDataModelUpdateRequested;
|
|
||||||
RightSideDataModel.UpdateRequested += RightDataModelUpdateRequested;
|
|
||||||
|
|
||||||
Update();
|
|
||||||
|
|
||||||
_updateTimer.Start();
|
|
||||||
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
|
|
||||||
|
|
||||||
IsInitialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Update()
|
|
||||||
{
|
|
||||||
if (LeftSideDataModel == null || DataModelConditionPredicate.PredicateType == ProfileRightSideType.Dynamic && RightSideDataModel == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If static, only allow selecting properties also supported by input
|
|
||||||
if (DataModelConditionPredicate.PredicateType == ProfileRightSideType.Static)
|
|
||||||
LeftSideDataModel.ApplyTypeFilter(false, _supportedInputTypes.ToArray());
|
|
||||||
|
|
||||||
// Determine the left side property first
|
|
||||||
SelectedLeftSideProperty = LeftSideDataModel.GetChildForCondition(DataModelConditionPredicate, DisplayConditionSide.Left);
|
|
||||||
var leftSideType = SelectedLeftSideProperty?.PropertyInfo?.PropertyType;
|
|
||||||
|
|
||||||
// Get the supported operators
|
|
||||||
Operators.Clear();
|
|
||||||
Operators.AddRange(_conditionOperatorService.GetConditionOperatorsForType(leftSideType));
|
|
||||||
if (DataModelConditionPredicate.Operator == null)
|
|
||||||
DataModelConditionPredicate.UpdateOperator(Operators.FirstOrDefault(o => o.SupportsType(leftSideType)));
|
|
||||||
SelectedOperator = DataModelConditionPredicate.Operator;
|
|
||||||
|
|
||||||
// Determine the right side
|
|
||||||
if (DataModelConditionPredicate.PredicateType == ProfileRightSideType.Dynamic)
|
|
||||||
{
|
|
||||||
SelectedRightSideProperty = LeftSideDataModel.GetChildForCondition(DataModelConditionPredicate, DisplayConditionSide.Right);
|
|
||||||
RightSideDataModel.ApplyTypeFilter(true, leftSideType);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
RightStaticValue = DataModelConditionPredicate.RightStaticValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyLeftSide()
|
|
||||||
{
|
|
||||||
DataModelConditionPredicate.UpdateLeftSide(SelectedLeftSideProperty.DataModel, SelectedLeftSideProperty.PropertyPath);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
SelectedOperator = DataModelConditionPredicate.Operator;
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyRightSideDynamic()
|
|
||||||
{
|
|
||||||
DataModelConditionPredicate.UpdateRightSide(SelectedRightSideProperty.DataModel, SelectedRightSideProperty.PropertyPath);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyRightSideStatic(object value, bool isSubmitted)
|
|
||||||
{
|
|
||||||
if (isSubmitted)
|
|
||||||
{
|
|
||||||
DataModelConditionPredicate.UpdateRightSide(value);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
RightSideTransitionIndex = 0;
|
|
||||||
RightSideInputViewModel = null;
|
|
||||||
RightStaticValue = value;
|
|
||||||
_eventAggregator.Unsubscribe(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ApplyOperator()
|
|
||||||
{
|
|
||||||
DataModelConditionPredicate.UpdateOperator(SelectedOperator);
|
|
||||||
_profileEditorService.UpdateSelectedProfileElement();
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ActivateRightSideInputViewModel()
|
|
||||||
{
|
|
||||||
if (SelectedLeftSideProperty?.PropertyInfo == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RightSideTransitionIndex = 1;
|
|
||||||
RightSideInputViewModel = _dataModelUIService.GetDataModelInputViewModel(
|
|
||||||
SelectedLeftSideProperty.PropertyInfo.PropertyType,
|
|
||||||
SelectedLeftSideProperty.PropertyDescription,
|
|
||||||
DataModelConditionPredicate.RightStaticValue,
|
|
||||||
ApplyRightSideStatic
|
|
||||||
);
|
|
||||||
_eventAggregator.Subscribe(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
|
|
||||||
{
|
|
||||||
if (LeftSideDataModelOpen)
|
|
||||||
LeftSideDataModel.Update(_dataModelUIService);
|
|
||||||
else if (RightSideDataModelOpen)
|
|
||||||
RightSideDataModel.Update(_dataModelUIService);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RightDataModelUpdateRequested(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var leftSideType = SelectedLeftSideProperty?.PropertyInfo?.PropertyType;
|
|
||||||
if (DataModelConditionPredicate.PredicateType == ProfileRightSideType.Dynamic)
|
|
||||||
SelectedRightSideProperty = LeftSideDataModel.GetChildForCondition(DataModelConditionPredicate, DisplayConditionSide.Right);
|
|
||||||
|
|
||||||
// With the data model updated, also reapply the filter
|
|
||||||
RightSideDataModel.ApplyTypeFilter(true, leftSideType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LeftDataModelUpdateRequested(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (DataModelConditionPredicate.PredicateType == ProfileRightSideType.Static)
|
|
||||||
LeftSideDataModel.ApplyTypeFilter(false, _supportedInputTypes.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSelectLeftProperty(object context)
|
|
||||||
{
|
|
||||||
if (!(context is DataModelVisualizationViewModel dataModelVisualizationViewModel))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SelectedLeftSideProperty = dataModelVisualizationViewModel;
|
|
||||||
ApplyLeftSide();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSelectRightProperty(object context)
|
|
||||||
{
|
|
||||||
if (!(context is DataModelVisualizationViewModel dataModelVisualizationViewModel))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SelectedRightSideProperty = dataModelVisualizationViewModel;
|
|
||||||
ApplyRightSideDynamic();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteSelectOperatorCommand(object context)
|
|
||||||
{
|
|
||||||
if (!(context is ConditionOperator displayConditionOperator))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SelectedOperator = displayConditionOperator;
|
|
||||||
ApplyOperator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_updateTimer.Dispose();
|
|
||||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,23 +1,24 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.UI.Ninject.Factories;
|
using Artemis.UI.Ninject.Factories;
|
||||||
|
using Artemis.UI.Screens.ProfileEditor.Conditions;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||||
{
|
{
|
||||||
public class DisplayConditionsViewModel : Conductor<DisplayConditionGroupViewModel>, IProfileEditorPanelViewModel
|
public class DisplayConditionsViewModel : Conductor<DataModelConditionGroupViewModel>, IProfileEditorPanelViewModel
|
||||||
{
|
{
|
||||||
private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory;
|
private readonly IDataModelConditionsVmFactory _dataModelConditionsVmFactory;
|
||||||
private readonly IProfileEditorService _profileEditorService;
|
private readonly IProfileEditorService _profileEditorService;
|
||||||
private RenderProfileElement _renderProfileElement;
|
private RenderProfileElement _renderProfileElement;
|
||||||
private bool _displayStartHint;
|
private bool _displayStartHint;
|
||||||
|
|
||||||
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IDisplayConditionsVmFactory displayConditionsVmFactory)
|
public DisplayConditionsViewModel(IProfileEditorService profileEditorService, IDataModelConditionsVmFactory dataModelConditionsVmFactory)
|
||||||
{
|
{
|
||||||
_profileEditorService = profileEditorService;
|
_profileEditorService = profileEditorService;
|
||||||
_displayConditionsVmFactory = displayConditionsVmFactory;
|
_dataModelConditionsVmFactory = dataModelConditionsVmFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DisplayStartHint
|
public bool DisplayStartHint
|
||||||
@ -82,10 +83,10 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the layer has a root display condition group
|
// Ensure the layer has a root display condition group
|
||||||
if (e.RenderProfileElement.DataModelConditionGroup == null)
|
if (e.RenderProfileElement.DisplayCondition == null)
|
||||||
e.RenderProfileElement.DataModelConditionGroup = new DataModelConditionGroup(null);
|
e.RenderProfileElement.DisplayCondition = new DataModelConditionGroup(null);
|
||||||
|
|
||||||
ActiveItem = _displayConditionsVmFactory.DisplayConditionGroupViewModel(e.RenderProfileElement.DataModelConditionGroup, false);
|
ActiveItem = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(e.RenderProfileElement.DisplayCondition, false);
|
||||||
ActiveItem.IsRootGroup = true;
|
ActiveItem.IsRootGroup = true;
|
||||||
ActiveItem.Update();
|
ActiveItem.Update();
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DisplayConditions.xaml" />
|
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DataModelConditions.xaml" />
|
||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DisplayConditions.xaml" />
|
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DataModelConditions.xaml" />
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||||
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
|
||||||
@ -51,7 +51,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button Grid.Column="2"
|
<Button Grid.Column="2"
|
||||||
Style="{StaticResource DisplayConditionButtonLeftClickMenu}"
|
Style="{StaticResource DataModelConditionButtonLeftClickMenu}"
|
||||||
Background="#7B7B7B"
|
Background="#7B7B7B"
|
||||||
BorderBrush="#7B7B7B"
|
BorderBrush="#7B7B7B"
|
||||||
Click="PropertyButton_OnClick">
|
Click="PropertyButton_OnClick">
|
||||||
|
|||||||
@ -114,7 +114,7 @@
|
|||||||
<!-- Conditions resize -->
|
<!-- Conditions resize -->
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<!-- Display conditions -->
|
<!-- Display conditions -->
|
||||||
<RowDefinition Height="{Binding DisplayConditionsHeight.Value, Mode=TwoWay}" MinHeight="100" />
|
<RowDefinition Height="{Binding DataModelConditionsHeight.Value, Mode=TwoWay}" MinHeight="100" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- Profile selection -->
|
<!-- Profile selection -->
|
||||||
|
|||||||
@ -25,7 +25,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
private readonly ISettingsService _settingsService;
|
private readonly ISettingsService _settingsService;
|
||||||
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
|
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
|
||||||
private PluginSetting<GridLength> _bottomPanelsHeight;
|
private PluginSetting<GridLength> _bottomPanelsHeight;
|
||||||
private PluginSetting<GridLength> _displayConditionsHeight;
|
private PluginSetting<GridLength> _dataModelConditionsHeight;
|
||||||
private DisplayConditionsViewModel _displayConditionsViewModel;
|
private DisplayConditionsViewModel _displayConditionsViewModel;
|
||||||
private PluginSetting<GridLength> _elementPropertiesWidth;
|
private PluginSetting<GridLength> _elementPropertiesWidth;
|
||||||
private LayerPropertiesViewModel _layerPropertiesViewModel;
|
private LayerPropertiesViewModel _layerPropertiesViewModel;
|
||||||
@ -38,7 +38,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
public ProfileEditorViewModel(ProfileModule module,
|
public ProfileEditorViewModel(ProfileModule module,
|
||||||
ProfileViewModel profileViewModel,
|
ProfileViewModel profileViewModel,
|
||||||
ProfileTreeViewModel profileTreeViewModel,
|
ProfileTreeViewModel profileTreeViewModel,
|
||||||
DisplayConditionsViewModel displayConditionsViewModel,
|
DisplayConditionsViewModel dataModelConditionsViewModel,
|
||||||
LayerPropertiesViewModel layerPropertiesViewModel,
|
LayerPropertiesViewModel layerPropertiesViewModel,
|
||||||
IProfileEditorService profileEditorService,
|
IProfileEditorService profileEditorService,
|
||||||
IProfileService profileService,
|
IProfileService profileService,
|
||||||
@ -62,12 +62,12 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
// Populate the panels
|
// Populate the panels
|
||||||
ProfileViewModel = profileViewModel;
|
ProfileViewModel = profileViewModel;
|
||||||
ProfileTreeViewModel = profileTreeViewModel;
|
ProfileTreeViewModel = profileTreeViewModel;
|
||||||
DisplayConditionsViewModel = displayConditionsViewModel;
|
DisplayConditionsViewModel = dataModelConditionsViewModel;
|
||||||
LayerPropertiesViewModel = layerPropertiesViewModel;
|
LayerPropertiesViewModel = layerPropertiesViewModel;
|
||||||
|
|
||||||
Items.Add(ProfileViewModel);
|
Items.Add(ProfileViewModel);
|
||||||
Items.Add(ProfileTreeViewModel);
|
Items.Add(ProfileTreeViewModel);
|
||||||
Items.Add(DisplayConditionsViewModel);
|
Items.Add(dataModelConditionsViewModel);
|
||||||
Items.Add(LayerPropertiesViewModel);
|
Items.Add(LayerPropertiesViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,10 +110,10 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
set => SetAndNotify(ref _sidePanelsWidth, value);
|
set => SetAndNotify(ref _sidePanelsWidth, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginSetting<GridLength> DisplayConditionsHeight
|
public PluginSetting<GridLength> DataModelConditionsHeight
|
||||||
{
|
{
|
||||||
get => _displayConditionsHeight;
|
get => _dataModelConditionsHeight;
|
||||||
set => SetAndNotify(ref _displayConditionsHeight, value);
|
set => SetAndNotify(ref _dataModelConditionsHeight, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginSetting<GridLength> BottomPanelsHeight
|
public PluginSetting<GridLength> BottomPanelsHeight
|
||||||
@ -303,7 +303,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
private void LoadWorkspaceSettings()
|
private void LoadWorkspaceSettings()
|
||||||
{
|
{
|
||||||
SidePanelsWidth = _settingsService.GetSetting("ProfileEditor.SidePanelsWidth", new GridLength(385));
|
SidePanelsWidth = _settingsService.GetSetting("ProfileEditor.SidePanelsWidth", new GridLength(385));
|
||||||
DisplayConditionsHeight = _settingsService.GetSetting("ProfileEditor.DisplayConditionsHeight", new GridLength(345));
|
DataModelConditionsHeight = _settingsService.GetSetting("ProfileEditor.DataModelConditionsHeight", new GridLength(345));
|
||||||
BottomPanelsHeight = _settingsService.GetSetting("ProfileEditor.BottomPanelsHeight", new GridLength(265));
|
BottomPanelsHeight = _settingsService.GetSetting("ProfileEditor.BottomPanelsHeight", new GridLength(265));
|
||||||
ElementPropertiesWidth = _settingsService.GetSetting("ProfileEditor.ElementPropertiesWidth", new GridLength(545));
|
ElementPropertiesWidth = _settingsService.GetSetting("ProfileEditor.ElementPropertiesWidth", new GridLength(545));
|
||||||
}
|
}
|
||||||
@ -311,7 +311,7 @@ namespace Artemis.UI.Screens.ProfileEditor
|
|||||||
private void SaveWorkspaceSettings()
|
private void SaveWorkspaceSettings()
|
||||||
{
|
{
|
||||||
SidePanelsWidth.Save();
|
SidePanelsWidth.Save();
|
||||||
DisplayConditionsHeight.Save();
|
DataModelConditionsHeight.Save();
|
||||||
BottomPanelsHeight.Save();
|
BottomPanelsHeight.Save();
|
||||||
ElementPropertiesWidth.Save();
|
ElementPropertiesWidth.Save();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user