mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Data model conditions - Added event predicates (WIP commit)
This commit is contained in:
parent
574c4b21ec
commit
fbd319beb9
@ -1,4 +1,5 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cconditions_005Cwrappers/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodes_005Cconditional/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cprofile_005Cdatabindings_005Cmodes_005Cdirect/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
@ -39,6 +40,7 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public DataModelPath? EventPath { get; private set; }
|
||||
|
||||
public Type? EventArgumentType { get; set; }
|
||||
|
||||
internal DataModelConditionEventEntity Entity { get; set; }
|
||||
|
||||
@ -57,6 +59,11 @@ namespace Artemis.Core
|
||||
return false;
|
||||
|
||||
_eventTriggered = false;
|
||||
|
||||
// If there is a child (root group), it must evaluate to true whenever the event triggered
|
||||
if (Children.Any())
|
||||
return Children[0].Evaluate();
|
||||
// If there are no children, we always evaluate to true whenever the event triggered
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -84,6 +91,31 @@ namespace Artemis.Core
|
||||
EventPath?.Dispose();
|
||||
EventPath = path != null ? new DataModelPath(path) : null;
|
||||
SubscribeToEventPath();
|
||||
|
||||
// Remove the old root group that was tied to the old data model
|
||||
while (Children.Any())
|
||||
RemoveChild(Children[0]);
|
||||
|
||||
if (EventPath != null)
|
||||
{
|
||||
EventArgumentType = GetEventArgumentType();
|
||||
// Create a new root group
|
||||
AddChild(new DataModelConditionGroup(this));
|
||||
}
|
||||
else
|
||||
{
|
||||
EventArgumentType = null;
|
||||
}
|
||||
}
|
||||
|
||||
private Type? GetEventArgumentType()
|
||||
{
|
||||
if (EventPath == null || !EventPath.IsValid)
|
||||
return null;
|
||||
|
||||
// Cannot rely on EventPath.GetValue() because part of the path might be null
|
||||
Type eventType = EventPath.GetPropertyType()!;
|
||||
return eventType.IsGenericType ? eventType.GetGenericArguments()[0] : typeof(DataModelEventArgs);
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
@ -117,6 +149,12 @@ namespace Artemis.Core
|
||||
// Target list
|
||||
EventPath?.Save();
|
||||
Entity.EventPath = EventPath?.Entity;
|
||||
|
||||
// Children
|
||||
Entity.Children.Clear();
|
||||
Entity.Children.AddRange(Children.Select(c => c.GetEntity()));
|
||||
foreach (DataModelConditionPart child in Children)
|
||||
child.Save();
|
||||
}
|
||||
|
||||
internal override DataModelConditionPartEntity GetEntity()
|
||||
@ -137,6 +175,18 @@ namespace Artemis.Core
|
||||
|
||||
EventPath = eventPath;
|
||||
SubscribeToEventPath();
|
||||
|
||||
EventArgumentType = GetEventArgumentType();
|
||||
// There should only be one child and it should be a group
|
||||
if (Entity.Children.FirstOrDefault() is DataModelConditionGroupEntity rootGroup)
|
||||
{
|
||||
AddChild(new DataModelConditionGroup(this, rootGroup));
|
||||
}
|
||||
else
|
||||
{
|
||||
Entity.Children.Clear();
|
||||
AddChild(new DataModelConditionGroup(this));
|
||||
}
|
||||
}
|
||||
|
||||
private bool PointsToEvent(DataModelPath dataModelPath)
|
||||
|
||||
@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A predicate like evaluated inside a <see cref="DataModelConditionEvent" />
|
||||
/// </summary>
|
||||
public class DataModelConditionEventPredicate : DataModelConditionPredicate
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelConditionEventPredicate" /> class
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
/// <param name="predicateType"></param>
|
||||
public DataModelConditionEventPredicate(DataModelConditionPart parent, ProfileRightSideType predicateType)
|
||||
: base(parent, predicateType, new DataModelConditionEventPredicateEntity())
|
||||
{
|
||||
DataModelConditionEvent = null!;
|
||||
ApplyParentEvent();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
internal DataModelConditionEventPredicate(DataModelConditionPart parent, DataModelConditionEventPredicateEntity entity)
|
||||
: base(parent, entity)
|
||||
{
|
||||
DataModelConditionEvent = null!;
|
||||
ApplyParentEvent();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the data model condition event this predicate belongs to
|
||||
/// </summary>
|
||||
public DataModelConditionEvent DataModelConditionEvent { get; private set; }
|
||||
|
||||
private void ApplyParentEvent()
|
||||
{
|
||||
DataModelConditionPart? current = Parent;
|
||||
while (current != null)
|
||||
{
|
||||
if (current is DataModelConditionEvent parentEvent)
|
||||
{
|
||||
DataModelConditionEvent = parentEvent;
|
||||
return;
|
||||
}
|
||||
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
if (DataModelConditionEvent == null)
|
||||
throw new ArtemisCoreException("This data model condition event predicate does not belong to a data model condition event");
|
||||
}
|
||||
|
||||
private object? GetEventPathValue(DataModelPath path, object target)
|
||||
{
|
||||
if (!(path.Target is EventPredicateWrapperDataModel wrapper))
|
||||
throw new ArtemisCoreException("Data model condition event predicate has a path with an invalid target");
|
||||
|
||||
wrapper.UntypedArguments = target;
|
||||
return path.GetValue();
|
||||
}
|
||||
|
||||
#region Initialization
|
||||
|
||||
protected override void InitializeLeftPath()
|
||||
{
|
||||
if (Entity.LeftPath != null)
|
||||
LeftPath = DataModelConditionEvent.EventArgumentType != null
|
||||
? new DataModelPath(EventPredicateWrapperDataModel.Create(DataModelConditionEvent.EventArgumentType), Entity.LeftPath)
|
||||
: null;
|
||||
}
|
||||
|
||||
protected override void InitializeRightPath()
|
||||
{
|
||||
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
||||
{
|
||||
// Right side dynamic using event arguments
|
||||
if (Entity.RightPath.WrapperType == PathWrapperType.Event)
|
||||
{
|
||||
RightPath = DataModelConditionEvent.EventArgumentType != null
|
||||
? new DataModelPath(EventPredicateWrapperDataModel.Create(DataModelConditionEvent.EventArgumentType), Entity.RightPath)
|
||||
: null;
|
||||
}
|
||||
// Right side dynamic
|
||||
else
|
||||
RightPath = new DataModelPath(null, Entity.RightPath);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Modification
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Type? GetPreferredRightSideType()
|
||||
{
|
||||
Type? preferredType = Operator?.RightSideType;
|
||||
Type? leftSideType = LeftPath?.GetPropertyType();
|
||||
if (preferredType == null)
|
||||
return null;
|
||||
|
||||
if (leftSideType != null && preferredType.IsAssignableFrom(leftSideType))
|
||||
preferredType = leftSideType;
|
||||
|
||||
return preferredType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Evaluation
|
||||
|
||||
/// <summary>
|
||||
/// Not supported for event predicates, always returns <c>false</c>
|
||||
/// </summary>
|
||||
public override bool Evaluate()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override bool EvaluateObject(object target)
|
||||
{
|
||||
if (Operator == null || LeftPath == null || !LeftPath.IsValid)
|
||||
return false;
|
||||
|
||||
// Compare with a static value
|
||||
if (PredicateType == ProfileRightSideType.Static)
|
||||
{
|
||||
object? leftSideValue = GetEventPathValue(LeftPath, target);
|
||||
if (leftSideValue != null && leftSideValue.GetType().IsValueType && RightStaticValue == null)
|
||||
return false;
|
||||
|
||||
return Operator.InternalEvaluate(leftSideValue, RightStaticValue);
|
||||
}
|
||||
|
||||
if (RightPath == null || !RightPath.IsValid)
|
||||
return false;
|
||||
|
||||
// Compare with dynamic values
|
||||
if (PredicateType == ProfileRightSideType.Dynamic)
|
||||
{
|
||||
// If the path targets a property inside the event, evaluate on the event path value instead of the right path value
|
||||
if (RightPath.Target is EventPredicateWrapperDataModel)
|
||||
return Operator.InternalEvaluate(GetEventPathValue(LeftPath, target), GetEventPathValue(RightPath, target));
|
||||
return Operator.InternalEvaluate(GetEventPathValue(LeftPath, target), RightPath.GetValue());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
namespace Artemis.Core
|
||||
@ -76,11 +77,12 @@ namespace Artemis.Core
|
||||
if (PredicateType == ProfileRightSideType.Dynamic && Entity.RightPath != null)
|
||||
{
|
||||
// Right side dynamic inside the list
|
||||
// TODO: Come up with a general wrapper solution because this will clash with events
|
||||
if (Entity.RightPath.DataModelGuid == Constants.CorePluginInfo.Guid)
|
||||
if (Entity.RightPath.WrapperType == PathWrapperType.List)
|
||||
{
|
||||
RightPath = DataModelConditionList.ListType != null
|
||||
? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), Entity.RightPath)
|
||||
: null;
|
||||
}
|
||||
// Right side dynamic
|
||||
else
|
||||
RightPath = new DataModelPath(null, Entity.RightPath);
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using Artemis.Core.DataModelExpansions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
internal class EventPredicateWrapperDataModel<T> : EventPredicateWrapperDataModel
|
||||
{
|
||||
[DataModelProperty(Name = "Event arguments", Description = "The arguments provided when the event triggers")]
|
||||
public T Arguments => (UntypedArguments is T typedArguments ? typedArguments : default)!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a datamodel that wraps the event arguments of an event
|
||||
/// </summary>
|
||||
public abstract class EventPredicateWrapperDataModel : DataModel
|
||||
{
|
||||
internal EventPredicateWrapperDataModel()
|
||||
{
|
||||
PluginInfo = Constants.CorePluginInfo;
|
||||
}
|
||||
|
||||
[DataModelIgnore]
|
||||
public object? UntypedArguments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="EventPredicateWrapperDataModel"/> class
|
||||
/// </summary>
|
||||
public static EventPredicateWrapperDataModel Create(Type type)
|
||||
{
|
||||
object? instance = Activator.CreateInstance(typeof(EventPredicateWrapperDataModel<>).MakeGenericType(type));
|
||||
if (instance == null)
|
||||
throw new ArtemisCoreException($"Failed to create an instance of EventPredicateWrapperDataModel<T> for type {type.Name}");
|
||||
|
||||
return (EventPredicateWrapperDataModel) instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,9 @@ namespace Artemis.Core
|
||||
public T Value => (UntypedValue is T typedValue ? typedValue : default)!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a datamodel that wraps a value in a list
|
||||
/// </summary>
|
||||
public abstract class ListPredicateWrapperDataModel : DataModel
|
||||
{
|
||||
internal ListPredicateWrapperDataModel()
|
||||
@ -19,6 +22,9 @@ namespace Artemis.Core
|
||||
[DataModelIgnore]
|
||||
public object? UntypedValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="ListPredicateWrapperDataModel"/> class
|
||||
/// </summary>
|
||||
public static ListPredicateWrapperDataModel Create(Type type)
|
||||
{
|
||||
object? instance = Activator.CreateInstance(typeof(ListPredicateWrapperDataModel<>).MakeGenericType(type));
|
||||
@ -58,6 +58,9 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public void Trigger()
|
||||
{
|
||||
DataModelEventArgs eventArgs = new DataModelEventArgs {TriggerTime = DateTime.Now};
|
||||
|
||||
LastEventArguments = eventArgs;
|
||||
LastTrigger = DateTime.Now;
|
||||
TriggerCount++;
|
||||
|
||||
@ -74,10 +77,15 @@ namespace Artemis.Core
|
||||
|
||||
/// <inheritdoc />
|
||||
public int TriggerCount { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the event arguments of the last time the event was triggered
|
||||
/// </summary>
|
||||
public DataModelEventArgs? LastEventArguments { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataModelIgnore]
|
||||
public Type? ArgumentsType => null;
|
||||
public Type ArgumentsType => typeof(DataModelEventArgs);
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? EventTriggered;
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the type of arguments this event contains
|
||||
/// </summary>
|
||||
Type? ArgumentsType { get; }
|
||||
Type ArgumentsType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Fires when the event is triggered
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
|
||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||
{
|
||||
@ -6,7 +7,7 @@ namespace Artemis.Storage.Entities.Profile.Conditions
|
||||
{
|
||||
public DataModelConditionEventEntity()
|
||||
{
|
||||
|
||||
Children = new List<DataModelConditionPartEntity>();
|
||||
}
|
||||
|
||||
public DataModelPathEntity EventPath { get; set; }
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||
{
|
||||
public class DataModelConditionEventPredicateEntity : DataModelConditionPredicateEntity
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -6,5 +6,14 @@ namespace Artemis.Storage.Entities.Profile
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public Guid? DataModelGuid { get; set; }
|
||||
|
||||
public PathWrapperType WrapperType { get; set; }
|
||||
}
|
||||
|
||||
public enum PathWrapperType
|
||||
{
|
||||
None,
|
||||
List,
|
||||
Event
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,7 @@
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=dependencyproperties/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=events/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=exceptions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=extensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=propertyinput/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cdatamodelvisualization/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cdialog/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
using Artemis.Core;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
{
|
||||
public static class DataModelWrapperExtensions
|
||||
{
|
||||
public static DataModelPropertiesViewModel CreateViewModel(this EventPredicateWrapperDataModel wrapper)
|
||||
{
|
||||
return new DataModelPropertiesViewModel(wrapper, null, new DataModelPath(wrapper));
|
||||
}
|
||||
|
||||
public static DataModelPropertiesViewModel CreateViewModel(this ListPredicateWrapperDataModel wrapper)
|
||||
{
|
||||
return new DataModelPropertiesViewModel(wrapper, null, new DataModelPath(wrapper));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -65,11 +65,12 @@ namespace Artemis.UI.Ninject.Factories
|
||||
|
||||
public interface IDataModelConditionsVmFactory : IVmFactory
|
||||
{
|
||||
DataModelConditionGroupViewModel DataModelConditionGroupViewModel(DataModelConditionGroup dataModelConditionGroup, bool isListGroup);
|
||||
DataModelConditionGroupViewModel DataModelConditionGroupViewModel(DataModelConditionGroup dataModelConditionGroup, ConditionGroupType groupType);
|
||||
DataModelConditionListViewModel DataModelConditionListViewModel(DataModelConditionList dataModelConditionList);
|
||||
DataModelConditionEventViewModel DataModelConditionEventViewModel(DataModelConditionEvent dataModelConditionEvent);
|
||||
DataModelConditionGeneralPredicateViewModel DataModelConditionGeneralPredicateViewModel(DataModelConditionGeneralPredicate dataModelConditionGeneralPredicate);
|
||||
DataModelConditionListPredicateViewModel DataModelConditionListPredicateViewModel(DataModelConditionListPredicate dataModelConditionListPredicate);
|
||||
DataModelConditionEventPredicateViewModel DataModelConditionEventPredicateViewModel(DataModelConditionEventPredicate dataModelConditionEventPredicate);
|
||||
}
|
||||
|
||||
public interface ILayerPropertyVmFactory : IVmFactory
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<UserControl x:Class="Artemis.UI.Screens.ProfileEditor.Conditions.DataModelConditionEventView"
|
||||
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: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.Conditions"
|
||||
xmlns:s="https://github.com/canton7/Stylet"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
mc:Ignorable="d"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
@ -21,9 +21,10 @@
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
ToolTip="Delete the event trigger"
|
||||
@ -43,5 +44,20 @@
|
||||
VerticalContentAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
IsTabStop="False" />
|
||||
|
||||
<TextBlock Grid.Row="0"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Margin="5 0 0 0">
|
||||
triggered
|
||||
</TextBlock>
|
||||
|
||||
<ItemsControl Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" ItemsSource="{Binding Items}" Margin="0 4 0 0">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentControl s:View.Model="{Binding}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -51,6 +51,31 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
public override void Update()
|
||||
{
|
||||
LeftSideSelectionViewModel.ChangeDataModelPath(DataModelConditionEvent.EventPath);
|
||||
|
||||
// Remove VMs of effects no longer applied on the layer
|
||||
Items.RemoveRange(Items.Where(c => !DataModelConditionEvent.Children.Contains(c.Model)).ToList());
|
||||
|
||||
if (DataModelConditionEvent.EventPath == null || !DataModelConditionEvent.EventPath.IsValid)
|
||||
return;
|
||||
|
||||
List<DataModelConditionViewModel> viewModels = new List<DataModelConditionViewModel>();
|
||||
foreach (DataModelConditionPart childModel in Model.Children)
|
||||
{
|
||||
if (Items.Any(c => c.Model == childModel))
|
||||
continue;
|
||||
if (!(childModel is DataModelConditionGroup dataModelConditionGroup))
|
||||
continue;
|
||||
|
||||
DataModelConditionGroupViewModel viewModel = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(dataModelConditionGroup, ConditionGroupType.Event);
|
||||
viewModel.IsRootGroup = true;
|
||||
viewModels.Add(viewModel);
|
||||
}
|
||||
|
||||
if (viewModels.Any())
|
||||
Items.AddRange(viewModels);
|
||||
|
||||
foreach (DataModelConditionViewModel childViewModel in Items)
|
||||
childViewModel.Update();
|
||||
}
|
||||
|
||||
public void ApplyEvent()
|
||||
|
||||
@ -21,12 +21,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
private bool _isRootGroup;
|
||||
|
||||
public DataModelConditionGroupViewModel(DataModelConditionGroup dataModelConditionGroup,
|
||||
bool isListGroup,
|
||||
ConditionGroupType groupType,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelConditionsVmFactory dataModelConditionsVmFactory)
|
||||
: base(dataModelConditionGroup)
|
||||
{
|
||||
IsListGroup = isListGroup;
|
||||
GroupType = groupType;
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelConditionsVmFactory = dataModelConditionsVmFactory;
|
||||
|
||||
@ -39,7 +39,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
});
|
||||
}
|
||||
|
||||
public bool IsListGroup { get; }
|
||||
public ConditionGroupType GroupType { get; set; }
|
||||
public DataModelConditionGroup DataModelConditionGroup => (DataModelConditionGroup) Model;
|
||||
|
||||
public bool IsRootGroup
|
||||
@ -68,10 +68,20 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
|
||||
public void AddCondition()
|
||||
{
|
||||
if (!IsListGroup)
|
||||
DataModelConditionGroup.AddChild(new DataModelConditionGeneralPredicate(DataModelConditionGroup, ProfileRightSideType.Dynamic));
|
||||
else
|
||||
DataModelConditionGroup.AddChild(new DataModelConditionListPredicate(DataModelConditionGroup, ProfileRightSideType.Dynamic));
|
||||
switch (GroupType)
|
||||
{
|
||||
case ConditionGroupType.General:
|
||||
DataModelConditionGroup.AddChild(new DataModelConditionGeneralPredicate(DataModelConditionGroup, ProfileRightSideType.Dynamic));
|
||||
break;
|
||||
case ConditionGroupType.List:
|
||||
DataModelConditionGroup.AddChild(new DataModelConditionListPredicate(DataModelConditionGroup, ProfileRightSideType.Dynamic));
|
||||
break;
|
||||
case ConditionGroupType.Event:
|
||||
DataModelConditionGroup.AddChild(new DataModelConditionEventPredicate(DataModelConditionGroup, ProfileRightSideType.Dynamic));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
Update();
|
||||
_profileEditorService.UpdateSelectedProfileElement();
|
||||
@ -101,7 +111,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
switch (childModel)
|
||||
{
|
||||
case DataModelConditionGroup dataModelConditionGroup:
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionGroupViewModel(dataModelConditionGroup, IsListGroup));
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionGroupViewModel(dataModelConditionGroup, GroupType));
|
||||
break;
|
||||
case DataModelConditionList dataModelConditionList:
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionListViewModel(dataModelConditionList));
|
||||
@ -110,12 +120,13 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionEventViewModel(dataModelConditionEvent));
|
||||
break;
|
||||
case DataModelConditionGeneralPredicate dataModelConditionGeneralPredicate:
|
||||
if (!IsListGroup)
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionGeneralPredicateViewModel(dataModelConditionGeneralPredicate));
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionGeneralPredicateViewModel(dataModelConditionGeneralPredicate));
|
||||
break;
|
||||
case DataModelConditionListPredicate dataModelConditionListPredicate:
|
||||
if (IsListGroup)
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionListPredicateViewModel(dataModelConditionListPredicate));
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionListPredicateViewModel(dataModelConditionListPredicate));
|
||||
break;
|
||||
case DataModelConditionEventPredicate dataModelConditionEventPredicate:
|
||||
viewModels.Add(_dataModelConditionsVmFactory.DataModelConditionEventPredicateViewModel(dataModelConditionEventPredicate));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -190,4 +201,11 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
Updated?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public enum ConditionGroupType
|
||||
{
|
||||
General,
|
||||
List,
|
||||
Event
|
||||
}
|
||||
}
|
||||
@ -115,7 +115,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
if (!(childModel is DataModelConditionGroup dataModelConditionGroup))
|
||||
continue;
|
||||
|
||||
DataModelConditionGroupViewModel viewModel = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(dataModelConditionGroup, true);
|
||||
DataModelConditionGroupViewModel viewModel = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(dataModelConditionGroup, ConditionGroupType.List);
|
||||
viewModel.IsRootGroup = true;
|
||||
viewModels.Add(viewModel);
|
||||
}
|
||||
|
||||
@ -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:DataModelConditions="clr-namespace:Artemis.UI.Screens.ProfileEditor.Conditions"
|
||||
x:Class="Artemis.UI.Screens.ProfileEditor.Conditions.DataModelConditionEventPredicateView"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance IsDesignTimeCreatable=False, Type={x:Type DataModelConditions:DataModelConditionEventPredicateViewModel}}">
|
||||
<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 -->
|
||||
<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>
|
||||
@ -0,0 +1,26 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for DataModelConditionEventPredicateView.xaml
|
||||
/// </summary>
|
||||
public partial class DataModelConditionEventPredicateView : UserControl
|
||||
{
|
||||
public DataModelConditionEventPredicateView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PropertyButton_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// DataContext is not set when using left button, I don't know why but there it is
|
||||
if (sender is Button button && button.ContextMenu != null)
|
||||
{
|
||||
button.ContextMenu.DataContext = button.DataContext;
|
||||
button.ContextMenu.IsOpen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Media;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Services;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
{
|
||||
public class DataModelConditionEventPredicateViewModel : DataModelConditionPredicateViewModel
|
||||
{
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
|
||||
public DataModelConditionEventPredicateViewModel(DataModelConditionEventPredicate dataModelConditionEventPredicate,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelUIService dataModelUIService,
|
||||
IConditionOperatorService conditionOperatorService,
|
||||
ISettingsService settingsService)
|
||||
: base(dataModelConditionEventPredicate, profileEditorService, dataModelUIService, conditionOperatorService, settingsService)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelUIService = dataModelUIService;
|
||||
|
||||
LeftSideColor = new SolidColorBrush(Color.FromRgb(185, 164, 10));
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public DataModelConditionEventPredicate DataModelConditionEventPredicate => (DataModelConditionEventPredicate) Model;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
DataModelPropertiesViewModel eventDataModel = GetEventDataModel();
|
||||
LeftSideSelectionViewModel.ChangeDataModel(eventDataModel);
|
||||
}
|
||||
|
||||
protected override List<Type> GetSupportedInputTypes()
|
||||
{
|
||||
IReadOnlyCollection<DataModelVisualizationRegistration> editors = _dataModelUIService.RegisteredDataModelEditors;
|
||||
List<Type> supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
|
||||
supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes));
|
||||
|
||||
return supportedInputTypes;
|
||||
}
|
||||
|
||||
protected override Type GetLeftSideType()
|
||||
{
|
||||
return LeftSideSelectionViewModel.DataModelPath?.GetPropertyType();
|
||||
}
|
||||
|
||||
protected override List<DataModelPropertiesViewModel> GetExtraRightSideDataModelViewModels()
|
||||
{
|
||||
return new List<DataModelPropertiesViewModel> {GetEventDataModel()};
|
||||
}
|
||||
|
||||
private DataModelPropertiesViewModel GetEventDataModel()
|
||||
{
|
||||
EventPredicateWrapperDataModel wrapper = EventPredicateWrapperDataModel.Create(
|
||||
DataModelConditionEventPredicate.DataModelConditionEvent.EventArgumentType
|
||||
);
|
||||
|
||||
return wrapper.CreateViewModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@
|
||||
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"
|
||||
@ -17,16 +16,7 @@
|
||||
<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>
|
||||
|
||||
@ -86,7 +86,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions
|
||||
if (e.RenderProfileElement.DisplayCondition == null)
|
||||
e.RenderProfileElement.DisplayCondition = new DataModelConditionGroup(null);
|
||||
|
||||
ActiveItem = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(e.RenderProfileElement.DisplayCondition, false);
|
||||
ActiveItem = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(e.RenderProfileElement.DisplayCondition, ConditionGroupType.General);
|
||||
ActiveItem.IsRootGroup = true;
|
||||
ActiveItem.Update();
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings.Conditio
|
||||
_profileEditorService = profileEditorService;
|
||||
DataBindingCondition = dataBindingCondition;
|
||||
|
||||
ActiveItem = dataModelConditionsVmFactory.DataModelConditionGroupViewModel(DataBindingCondition.Condition, false);
|
||||
ActiveItem = dataModelConditionsVmFactory.DataModelConditionGroupViewModel(DataBindingCondition.Condition, ConditionGroupType.General);
|
||||
ActiveItem.IsRootGroup = true;
|
||||
ActiveItem.Update();
|
||||
ActiveItem.Updated += ActiveItemOnUpdated;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user