mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Data model events - WIP commit
This commit is contained in:
parent
b8112601df
commit
03b0e83ed8
@ -13,20 +13,30 @@ namespace Artemis.Core
|
||||
/// <param name="a">The parameter on the left side of the expression</param>
|
||||
/// <param name="b">The parameter on the right side of the expression</param>
|
||||
public abstract bool Evaluate(TLeftSide a, TRightSide b);
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
internal override bool InternalEvaluate(object? leftSideValue, object? rightSideValue)
|
||||
{
|
||||
// TODO: Can we avoid boxing/unboxing?
|
||||
TLeftSide leftSide;
|
||||
if (leftSideValue != null)
|
||||
leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide));
|
||||
{
|
||||
if (leftSideValue.GetType() != typeof(TLeftSide))
|
||||
leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide));
|
||||
else
|
||||
leftSide = (TLeftSide) leftSideValue;
|
||||
}
|
||||
else
|
||||
leftSide = default;
|
||||
|
||||
TRightSide rightSide;
|
||||
if (rightSideValue != null)
|
||||
rightSide = (TRightSide) Convert.ChangeType(rightSideValue, typeof(TRightSide));
|
||||
{
|
||||
if (rightSideValue.GetType() != typeof(TRightSide))
|
||||
rightSide = (TRightSide) Convert.ChangeType(rightSideValue, typeof(TRightSide));
|
||||
else
|
||||
rightSide = (TRightSide) rightSideValue;
|
||||
}
|
||||
else
|
||||
rightSide = default;
|
||||
|
||||
@ -57,7 +67,12 @@ namespace Artemis.Core
|
||||
// TODO: Can we avoid boxing/unboxing?
|
||||
TLeftSide leftSide;
|
||||
if (leftSideValue != null)
|
||||
leftSide = (TLeftSide) Convert.ChangeType(leftSideValue, typeof(TLeftSide));
|
||||
{
|
||||
if (leftSideValue.GetType() != typeof(TLeftSide))
|
||||
leftSide = (TLeftSide)Convert.ChangeType(leftSideValue, typeof(TLeftSide));
|
||||
else
|
||||
leftSide = (TLeftSide)leftSideValue;
|
||||
}
|
||||
else
|
||||
leftSide = default;
|
||||
|
||||
|
||||
@ -0,0 +1,189 @@
|
||||
using System;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A condition that evaluates to true when an event is triggered
|
||||
/// </summary>
|
||||
public class DataModelConditionEvent : DataModelConditionPart
|
||||
{
|
||||
private bool _disposed;
|
||||
private bool _reinitializing;
|
||||
private IDataModelEvent? _event;
|
||||
private bool _eventTriggered;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="DataModelConditionEvent" /> class
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
public DataModelConditionEvent(DataModelConditionPart parent)
|
||||
{
|
||||
Parent = parent;
|
||||
Entity = new DataModelConditionEventEntity();
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
internal DataModelConditionEvent(DataModelConditionPart parent, DataModelConditionEventEntity entity)
|
||||
{
|
||||
Parent = parent;
|
||||
Entity = entity;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path of the event property
|
||||
/// </summary>
|
||||
public DataModelPath? EventPath { get; private set; }
|
||||
|
||||
|
||||
internal DataModelConditionEventEntity Entity { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Evaluate()
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataModelConditionEvent");
|
||||
|
||||
// Ensure the event has not been replaced
|
||||
if (EventPath?.GetValue() is IDataModelEvent dataModelEvent && _event != dataModelEvent)
|
||||
SubscribeToDataModelEvent(dataModelEvent);
|
||||
|
||||
// Only evaluate to true once every time the event has been triggered
|
||||
if (!_eventTriggered)
|
||||
return false;
|
||||
|
||||
_eventTriggered = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SubscribeToDataModelEvent(IDataModelEvent dataModelEvent)
|
||||
{
|
||||
if (_event != null)
|
||||
_event.EventTriggered -= OnEventTriggered;
|
||||
|
||||
_event = dataModelEvent;
|
||||
if (_event != null)
|
||||
_event.EventTriggered += OnEventTriggered;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the event the condition is triggered by
|
||||
/// </summary>
|
||||
public void UpdateEvent(DataModelPath? path)
|
||||
{
|
||||
if (_disposed)
|
||||
throw new ObjectDisposedException("DataModelConditionEvent");
|
||||
|
||||
if (path != null && !path.IsValid)
|
||||
throw new ArtemisCoreException("Cannot update event to an invalid path");
|
||||
|
||||
EventPath?.Dispose();
|
||||
EventPath = path != null ? new DataModelPath(path) : null;
|
||||
SubscribeToEventPath();
|
||||
}
|
||||
|
||||
#region IDisposable
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
_disposed = true;
|
||||
|
||||
EventPath?.Dispose();
|
||||
|
||||
foreach (DataModelConditionPart child in Children)
|
||||
child.Dispose();
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
internal override bool EvaluateObject(object target)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
internal override void Save()
|
||||
{
|
||||
// Don't save an invalid state
|
||||
if (EventPath != null && !EventPath.IsValid)
|
||||
return;
|
||||
|
||||
// Target list
|
||||
EventPath?.Save();
|
||||
Entity.EventPath = EventPath?.Entity;
|
||||
}
|
||||
|
||||
internal override DataModelConditionPartEntity GetEntity()
|
||||
{
|
||||
return Entity;
|
||||
}
|
||||
|
||||
internal void Initialize()
|
||||
{
|
||||
if (Entity.EventPath == null)
|
||||
return;
|
||||
|
||||
// Ensure the list path is valid and points to a list
|
||||
DataModelPath eventPath = new DataModelPath(null, Entity.EventPath);
|
||||
// Can't check this on an invalid list, if it becomes valid later lets hope for the best
|
||||
if (eventPath.IsValid && !PointsToEvent(eventPath))
|
||||
return;
|
||||
|
||||
EventPath = eventPath;
|
||||
SubscribeToEventPath();
|
||||
}
|
||||
|
||||
private bool PointsToEvent(DataModelPath dataModelPath)
|
||||
{
|
||||
Type? type = dataModelPath.GetPropertyType();
|
||||
if (type == null)
|
||||
return false;
|
||||
|
||||
return typeof(IDataModelEvent).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
private void SubscribeToEventPath()
|
||||
{
|
||||
if (EventPath == null) return;
|
||||
EventPath.PathValidated += EventPathOnPathValidated;
|
||||
EventPath.PathInvalidated += EventPathOnPathInvalidated;
|
||||
}
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void OnEventTriggered(object? sender, EventArgs e)
|
||||
{
|
||||
_eventTriggered = true;
|
||||
}
|
||||
|
||||
private void EventPathOnPathValidated(object? sender, EventArgs e)
|
||||
{
|
||||
if (_reinitializing)
|
||||
return;
|
||||
|
||||
_reinitializing = true;
|
||||
EventPath?.Dispose();
|
||||
Initialize();
|
||||
_reinitializing = false;
|
||||
}
|
||||
|
||||
private void EventPathOnPathInvalidated(object? sender, EventArgs e)
|
||||
{
|
||||
if (_reinitializing)
|
||||
return;
|
||||
|
||||
_reinitializing = true;
|
||||
EventPath?.Dispose();
|
||||
Initialize();
|
||||
_reinitializing = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -180,7 +180,7 @@ namespace Artemis.Core
|
||||
DataModelPath listPath = new DataModelPath(null, Entity.ListPath);
|
||||
Type listType = listPath.GetPropertyType()!;
|
||||
// Can't check this on an invalid list, if it becomes valid later lets hope for the best
|
||||
if (listPath.IsValid && !listPath.PointsToList)
|
||||
if (listPath.IsValid && !PointsToList(listPath))
|
||||
return;
|
||||
|
||||
ListPath = listPath;
|
||||
@ -208,6 +208,12 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
private bool PointsToList(DataModelPath dataModelPath)
|
||||
{
|
||||
Type? type = dataModelPath.GetPropertyType();
|
||||
return type?.IsGenericEnumerable() ?? false;
|
||||
}
|
||||
|
||||
private void SubscribeToListPath()
|
||||
{
|
||||
if (ListPath == null) return;
|
||||
|
||||
85
src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs
Normal file
85
src/Artemis.Core/Models/Profile/DataModel/DataModelEvent.cs
Normal file
@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using Artemis.Core.DataModelExpansions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a data model event with event arguments of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
public class DataModelEvent<T> : IDataModelEvent where T : DataModelEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Trigger the event with the given <paramref name="eventArgs" />
|
||||
/// </summary>
|
||||
/// <param name="eventArgs">The event argument to pass to the event</param>
|
||||
public void Trigger(T eventArgs)
|
||||
{
|
||||
if (eventArgs == null) throw new ArgumentNullException(nameof(eventArgs));
|
||||
eventArgs.TriggerTime = DateTime.Now;
|
||||
|
||||
LastEventArguments = eventArgs;
|
||||
LastTrigger = DateTime.Now;
|
||||
TriggerCount++;
|
||||
|
||||
OnEventTriggered();
|
||||
}
|
||||
|
||||
internal virtual void OnEventTriggered()
|
||||
{
|
||||
EventTriggered?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime LastTrigger { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int TriggerCount { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the event arguments of the last time the event was triggered
|
||||
/// </summary>
|
||||
public T? LastEventArguments { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataModelIgnore]
|
||||
public Type ArgumentsType => typeof(T);
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? EventTriggered;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a data model event without event arguments
|
||||
/// </summary>
|
||||
public class DataModelEvent : IDataModelEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Trigger the event
|
||||
/// </summary>
|
||||
public void Trigger()
|
||||
{
|
||||
LastTrigger = DateTime.Now;
|
||||
TriggerCount++;
|
||||
|
||||
OnEventTriggered();
|
||||
}
|
||||
|
||||
internal virtual void OnEventTriggered()
|
||||
{
|
||||
EventTriggered?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public DateTime LastTrigger { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int TriggerCount { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[DataModelIgnore]
|
||||
public Type? ArgumentsType => null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler? EventTriggered;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the base class for data model events that contain event data
|
||||
/// </summary>
|
||||
public class DataModelEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the time at which the event with these arguments was triggered
|
||||
/// </summary>
|
||||
public DateTime TriggerTime { get; internal set; }
|
||||
}
|
||||
}
|
||||
@ -111,18 +111,6 @@ namespace Artemis.Core
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<DataModelPathSegment> Segments => _segments.ToList().AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a boolean indicating whether this data model path points to a list
|
||||
/// </summary>
|
||||
public bool PointsToList
|
||||
{
|
||||
get
|
||||
{
|
||||
Type? type = GetPropertyType();
|
||||
return type?.IsGenericEnumerable() ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
internal DataModelPathEntity Entity { get; }
|
||||
|
||||
internal Func<object, object>? Accessor { get; private set; }
|
||||
|
||||
27
src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs
Normal file
27
src/Artemis.Core/Models/Profile/DataModel/IDataModelEvent.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
internal interface IDataModelEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the last time the event was triggered
|
||||
/// </summary>
|
||||
DateTime LastTrigger { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of times the event was triggered
|
||||
/// </summary>
|
||||
int TriggerCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of arguments this event contains
|
||||
/// </summary>
|
||||
Type? ArgumentsType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Fires when the event is triggered
|
||||
/// </summary>
|
||||
event EventHandler EventTriggered;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
|
||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||
{
|
||||
public class DataModelConditionEventEntity : DataModelConditionPartEntity
|
||||
{
|
||||
public DataModelConditionEventEntity()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public DataModelPathEntity EventPath { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Storage.Entities.Profile.Abstract;
|
||||
|
||||
namespace Artemis.Storage.Entities.Profile.Conditions
|
||||
|
||||
@ -1,2 +1,14 @@
|
||||
<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/=behaviors/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=controls/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=converters/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=datamodelvisualization/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=datamodelvisualization_005Cshared/@EntryIndexedValue">True</s:Boolean>
|
||||
<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/=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>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=utilities/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@ -0,0 +1,33 @@
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.DataModelExpansions;
|
||||
using Artemis.UI.Shared.Services;
|
||||
|
||||
namespace Artemis.UI.Shared
|
||||
{
|
||||
public class DataModelEventViewModel : DataModelVisualizationViewModel
|
||||
{
|
||||
internal DataModelEventViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Update(IDataModelUIService dataModelUIService)
|
||||
{
|
||||
}
|
||||
|
||||
public override object GetCurrentValue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return DisplayPath ?? Path;
|
||||
}
|
||||
|
||||
internal override int GetChildDepth()
|
||||
{
|
||||
return PropertyDescription != null && !PropertyDescription.ResetsDepth ? Depth + 1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,8 +7,8 @@ namespace Artemis.UI.Shared
|
||||
{
|
||||
public class DataModelPropertiesViewModel : DataModelVisualizationViewModel
|
||||
{
|
||||
private Type _displayValueType;
|
||||
private object _displayValue;
|
||||
private Type _displayValueType;
|
||||
|
||||
internal DataModelPropertiesViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, DataModelPath dataModelPath) : base(dataModel, parent, dataModelPath)
|
||||
{
|
||||
@ -29,15 +29,15 @@ namespace Artemis.UI.Shared
|
||||
public override void Update(IDataModelUIService dataModelUIService)
|
||||
{
|
||||
DisplayValueType = DataModelPath?.GetPropertyType();
|
||||
|
||||
|
||||
// Only set a display value if ToString returns useful information and not just the type name
|
||||
object currentValue = GetCurrentValue();
|
||||
if (currentValue != null && currentValue.ToString() != currentValue.GetType().ToString())
|
||||
DisplayValue = currentValue.ToString();
|
||||
else
|
||||
DisplayValue = null;
|
||||
|
||||
// Always populate properties
|
||||
|
||||
// Always populate properties
|
||||
PopulateProperties(dataModelUIService);
|
||||
|
||||
// Only update children if the parent is expanded
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
@ -137,7 +136,8 @@ namespace Artemis.UI.Shared
|
||||
if (looseMatch)
|
||||
IsMatchingFilteredTypes = filteredTypes.Any(t => t.IsCastableFrom(type) ||
|
||||
t == typeof(Enum) && type.IsEnum ||
|
||||
t == typeof(IEnumerable<>) && type.IsGenericEnumerable());
|
||||
t == typeof(IEnumerable<>) && type.IsGenericEnumerable() ||
|
||||
type.IsGenericType && t == type.GetGenericTypeDefinition());
|
||||
else
|
||||
IsMatchingFilteredTypes = filteredTypes.Any(t => t == type || t == typeof(Enum) && type.IsEnum);
|
||||
}
|
||||
@ -219,7 +219,6 @@ namespace Artemis.UI.Shared
|
||||
// Add missing dynamic children
|
||||
object value = Parent == null || Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue();
|
||||
if (value is DataModel dataModel)
|
||||
{
|
||||
foreach (KeyValuePair<string, DataModel> kvp in dataModel.DynamicDataModels)
|
||||
{
|
||||
string childPath = AppendToPath(kvp.Key);
|
||||
@ -230,7 +229,6 @@ namespace Artemis.UI.Shared
|
||||
if (child != null)
|
||||
Children.Add(child);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove dynamic children that have been removed from the data model
|
||||
List<DataModelVisualizationViewModel> toRemoveDynamic = Children.Where(c => !c.DataModelPath.IsValid).ToList();
|
||||
@ -266,6 +264,8 @@ namespace Artemis.UI.Shared
|
||||
return new DataModelPropertyViewModel(DataModel, this, dataModelPath) {Depth = depth};
|
||||
if (propertyType.IsGenericEnumerable())
|
||||
return new DataModelListViewModel(DataModel, this, dataModelPath) {Depth = depth};
|
||||
if (propertyType == typeof(DataModelEvent) || propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(DataModelEvent<>))
|
||||
return new DataModelEventViewModel(DataModel, this, dataModelPath) { Depth = depth };
|
||||
// For other value types create a child view model
|
||||
if (propertyType.IsClass || propertyType.IsStruct())
|
||||
return new DataModelPropertiesViewModel(DataModel, this, dataModelPath) {Depth = depth};
|
||||
|
||||
@ -39,6 +39,12 @@
|
||||
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" ToolTipService.ShowOnDisabled="True" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type dataModel:DataModelEventViewModel}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="LightningBolt" VerticalAlignment="Center" Margin="0 0 5 0" />
|
||||
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="Trigger layer on event" ToolTipService.ShowOnDisabled="True" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
|
||||
<Grid>
|
||||
<!-- Value description -->
|
||||
@ -73,6 +79,12 @@
|
||||
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" ToolTipService.ShowOnDisabled="True" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type dataModel:DataModelEventViewModel}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<materialDesign:PackIcon Kind="LightningBolt" VerticalAlignment="Center" Margin="0 0 5 0" />
|
||||
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" ToolTipService.ShowOnDisabled="True" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
|
||||
<Grid ToolTip="{Binding PropertyDescription.Description}">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
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;
|
||||
|
||||
namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
{
|
||||
public class DataModelConditionEventViewModel : DataModelConditionViewModel, IDisposable
|
||||
{
|
||||
private readonly IDataModelConditionsVmFactory _dataModelConditionsVmFactory;
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private DataModelDynamicViewModel _targetSelectionViewModel;
|
||||
|
||||
public DataModelConditionEventViewModel(DataModelConditionEvent model,
|
||||
IProfileEditorService profileEditorService,
|
||||
IDataModelUIService dataModelUIService,
|
||||
IDataModelConditionsVmFactory dataModelConditionsVmFactory) : base(model)
|
||||
{
|
||||
_profileEditorService = profileEditorService;
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_dataModelConditionsVmFactory = dataModelConditionsVmFactory;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public DataModelConditionEvent DataModelConditionEvent => (DataModelConditionEvent) Model;
|
||||
|
||||
public DataModelDynamicViewModel TargetSelectionViewModel
|
||||
{
|
||||
get => _targetSelectionViewModel;
|
||||
set => SetAndNotify(ref _targetSelectionViewModel, value);
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
TargetSelectionViewModel = _dataModelUIService.GetDynamicSelectionViewModel(_profileEditorService.GetCurrentModule());
|
||||
TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected;
|
||||
|
||||
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));
|
||||
supportedInputTypes.Add(typeof(IEnumerable<>));
|
||||
TargetSelectionViewModel.FilterTypes = supportedInputTypes.ToArray();
|
||||
|
||||
TargetSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(188, 174, 71));
|
||||
TargetSelectionViewModel.Placeholder = "Select a list";
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
public void ApplyEvent()
|
||||
{
|
||||
if (!TargetSelectionViewModel.DataModelPath.GetPropertyType().IsGenericEnumerable())
|
||||
{
|
||||
if (Parent is DataModelConditionGroupViewModel groupViewModel)
|
||||
groupViewModel.ConvertToPredicate(this);
|
||||
return;
|
||||
}
|
||||
|
||||
DataModelConditionEvent.UpdateEvent(TargetSelectionViewModel.DataModelPath);
|
||||
_profileEditorService.UpdateSelectedProfileElement();
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void TargetSelectionViewModelOnPropertySelected(object? sender, DataModelInputDynamicEventArgs e)
|
||||
{
|
||||
ApplyEvent();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
TargetSelectionViewModel.Dispose();
|
||||
TargetSelectionViewModel.PropertySelected -= TargetSelectionViewModelOnPropertySelected;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -147,6 +147,24 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
Update();
|
||||
}
|
||||
|
||||
public void ConvertToConditionEvent(DataModelConditionPredicateViewModel predicateViewModel)
|
||||
{
|
||||
// Remove the old child
|
||||
DataModelConditionGroup.RemoveChild(predicateViewModel.Model);
|
||||
|
||||
DataModelConditionPart rootGroup = DataModelConditionGroup;
|
||||
while (rootGroup.Parent != null)
|
||||
rootGroup = rootGroup.Parent;
|
||||
|
||||
// Insert an event at the start of the root group
|
||||
DataModelConditionEvent conditionEvent = new DataModelConditionEvent(rootGroup);
|
||||
conditionEvent.UpdateEvent(predicateViewModel.LeftSideSelectionViewModel.DataModelPath);
|
||||
rootGroup.AddChild(conditionEvent, 0);
|
||||
|
||||
// Update to switch the VMs
|
||||
Update();
|
||||
}
|
||||
|
||||
public void ConvertToPredicate(DataModelConditionListViewModel listViewModel)
|
||||
{
|
||||
// Store the old index and remove the old predicate
|
||||
|
||||
@ -97,6 +97,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
_supportedInputTypes = editors.Select(e => e.SupportedType).ToList();
|
||||
_supportedInputTypes.AddRange(editors.Where(e => e.CompatibleConversionTypes != null).SelectMany(e => e.CompatibleConversionTypes));
|
||||
_supportedInputTypes.Add(typeof(IEnumerable<>));
|
||||
_supportedInputTypes.Add(typeof(DataModelEvent));
|
||||
_supportedInputTypes.Add(typeof(DataModelEvent<>));
|
||||
Update();
|
||||
}
|
||||
|
||||
@ -278,7 +280,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
|
||||
Update();
|
||||
}
|
||||
|
||||
|
||||
private void RightSideInputViewModelOnSwitchToDynamicRequested(object? sender, EventArgs e)
|
||||
{
|
||||
DataModelConditionPredicate.PredicateType = ProfileRightSideType.Dynamic;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.DataModelExpansions;
|
||||
using SkiaSharp;
|
||||
|
||||
@ -34,6 +35,22 @@ namespace Artemis.Plugins.DataModelExpansions.TestData.DataModels
|
||||
public bool IsWinning { get; set; }
|
||||
|
||||
public List<SomeListItem> ListItems { get; set; }
|
||||
|
||||
[DataModelProperty(Description = "Event without arguments")]
|
||||
public DataModelEvent Event1 { get; set; } = new DataModelEvent();
|
||||
|
||||
[DataModelProperty(Description = "Event with arguments")]
|
||||
public DataModelEvent<TestEventArgs> Event2 { get; set; } = new DataModelEvent<TestEventArgs>();
|
||||
}
|
||||
|
||||
public class TestEventArgs : DataModelEventArgs
|
||||
{
|
||||
public TestEventArgs(string someValue)
|
||||
{
|
||||
SomeValue = someValue;
|
||||
}
|
||||
|
||||
public string SomeValue { get; set; }
|
||||
}
|
||||
|
||||
public class Test<T>
|
||||
|
||||
@ -23,6 +23,8 @@ namespace Artemis.Plugins.DataModelExpansions.TestData
|
||||
{
|
||||
// You can access your data model here and update it however you like
|
||||
DataModel.TemplateDataModelString = $"The last delta time was {deltaTime} seconds";
|
||||
|
||||
// DataModel.Event1.Trigger();
|
||||
}
|
||||
|
||||
private void TimedUpdate(double deltaTime)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user