1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-01-01 18:23:32 +00:00

Conditions - Finished migration to new API

Conditions UI - Updated for new API, needs simplifying before I'm happy with it
This commit is contained in:
Robert 2020-10-08 20:49:23 +02:00
parent 725bb2a128
commit 805cdc6782
10 changed files with 91 additions and 75 deletions

View File

@ -96,8 +96,8 @@ namespace Artemis.Core
throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{newPath}'"); throw new ArtemisCoreException($"Data model of type {dataModel.GetType().Name} does not contain a list at path '{newPath}'");
ListPath = newPath; ListPath = newPath;
ListType = listType; ListType = listType.GetGenericArguments()[0];
IsPrimitiveList = listType.IsPrimitive || listType.IsEnum || listType == typeof(string); IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
} }
else else
{ {
@ -182,10 +182,13 @@ namespace Artemis.Core
// Ensure the list path is valid and points to a list // Ensure the list path is valid and points to a list
DataModelPath listPath = new DataModelPath(null, Entity.ListPath); DataModelPath listPath = new DataModelPath(null, Entity.ListPath);
if (!listPath.IsValid || !typeof(IList).IsAssignableFrom(listPath.GetPropertyType())) Type listType = listPath.GetPropertyType()!;
if (!listPath.IsValid || !typeof(IList).IsAssignableFrom(listType))
return; return;
ListPath = listPath; ListPath = listPath;
ListType = listType.GetGenericArguments()[0];
IsPrimitiveList = ListType.IsPrimitive || ListType.IsEnum || ListType == typeof(string);
// 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 DataModelConditionGroupEntity rootGroup) if (Entity.Children.SingleOrDefault() is DataModelConditionGroupEntity rootGroup)

View File

@ -70,18 +70,17 @@ namespace Artemis.Core
/// 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 (DataModelConditionList.IsPrimitiveList) if (DataModelConditionList.IsPrimitiveList)
throw new ArtemisCoreException("Cannot apply a left side to a predicate inside a primitive list"); throw new ArtemisCoreException("Cannot apply a left side to a predicate inside a primitive list");
if (!ListContainsInnerPath(path))
throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}");
LeftPath?.Dispose(); LeftPath?.Dispose();
LeftPath = DataModelConditionList.ListType != null if (path != null && DataModelConditionList.ListType != null)
? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path) LeftPath = new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path);
: null; else
LeftPath = null;
ValidateOperator(); ValidateOperator();
ValidateRightSide(); ValidateRightSide();
} }
@ -91,16 +90,15 @@ namespace Artemis.Core
/// and re-compiles the expression /// 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)
{ {
if (!ListContainsInnerPath(path)) RightPath?.Dispose();
throw new ArtemisCoreException($"List type {DataModelConditionList.ListType.Name} does not contain path {path}"); if (path != null && DataModelConditionList.ListType != null)
RightPath = new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path);
else
RightPath = null;
PredicateType = ListRightSideType.DynamicList; PredicateType = ListRightSideType.DynamicList;
RightPath?.Dispose();
RightPath = DataModelConditionList.ListType != null
? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), path)
: null;
} }
/// <summary> /// <summary>
@ -109,20 +107,27 @@ namespace Artemis.Core
/// </summary> /// </summary>
/// <param name="dataModel"></param> /// <param name="dataModel"></param>
/// <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(DataModel dataModel, string path) public void UpdateRightSideDynamic(DataModel? dataModel, string? path)
{ {
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");
if (dataModel == null && path != null) if (dataModel == null && path != null)
throw new ArtemisCoreException("If path is provided, a data model is also required"); throw new ArtemisCoreException("If path is provided, a data model is also required");
RightPath?.Dispose();
if (dataModel != null) 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}'"); DataModelPath newPath = new DataModelPath(dataModel, path);
if (!newPath.IsValid)
throw new ArtemisCoreException($"New right path '{newPath}' is invalid");
RightPath = newPath;
}
else
{
RightPath = null;
}
PredicateType = ListRightSideType.Dynamic; PredicateType = ListRightSideType.Dynamic;
RightPath?.Dispose();
RightPath = new DataModelPath(dataModel, path);
} }
/// <summary> /// <summary>

View File

@ -76,7 +76,7 @@ namespace Artemis.Core
throw new ArtemisCoreException("If path is provided, a data model is also required"); throw new ArtemisCoreException("If path is provided, a data model is also required");
LeftPath?.Dispose(); LeftPath?.Dispose();
if (dataModel != null && path != null) if (dataModel != null)
{ {
DataModelPath newPath = new DataModelPath(dataModel, path); DataModelPath newPath = new DataModelPath(dataModel, path);
if (!newPath.IsValid) if (!newPath.IsValid)
@ -105,7 +105,7 @@ namespace Artemis.Core
throw new ArtemisCoreException("If path is provided, a data model is also required"); throw new ArtemisCoreException("If path is provided, a data model is also required");
RightPath?.Dispose(); RightPath?.Dispose();
if (dataModel != null && path != null) if (dataModel != null)
{ {
DataModelPath newPath = new DataModelPath(dataModel, path); DataModelPath newPath = new DataModelPath(dataModel, path);
if (!newPath.IsValid) if (!newPath.IsValid)

View File

@ -10,6 +10,12 @@ namespace Artemis.Core
public abstract class ListPredicateWrapperDataModel : DataModel public abstract class ListPredicateWrapperDataModel : DataModel
{ {
internal ListPredicateWrapperDataModel()
{
PluginInfo = Constants.CorePluginInfo;
}
[DataModelIgnore]
public object? UntypedValue { get; set; } public object? UntypedValue { get; set; }
public static ListPredicateWrapperDataModel Create(Type type) public static ListPredicateWrapperDataModel Create(Type type)

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Linq;
using Artemis.Core; using Artemis.Core;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
@ -10,11 +11,12 @@ namespace Artemis.UI.Shared
private int _index; private int _index;
private Type _listType; private Type _listType;
public DataModelListPropertiesViewModel(object listItem) : base(null, null, null) public DataModelListPropertiesViewModel(Type listType) : base(null, null, null)
{ {
DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType()); DataModel = ListPredicateWrapperDataModel.Create(listType);
ListType = listItem.GetType(); ListType = listType;
DisplayValue = listItem;
IsRootViewModel = false;
} }
public int Index public int Index
@ -35,18 +37,21 @@ namespace Artemis.UI.Shared
set => SetAndNotify(ref _displayValue, value); set => SetAndNotify(ref _displayValue, value);
} }
public DataModelVisualizationViewModel DisplayViewModel => Children.FirstOrDefault();
public override string DisplayPath => null; public override string DisplayPath => null;
public override void Update(IDataModelUIService dataModelUIService) public override void Update(IDataModelUIService dataModelUIService)
{ {
// Display value gets updated by parent, don't do anything if it is null ((ListPredicateWrapperDataModel) DataModel).UntypedValue = DisplayValue;
if (DisplayValue == null)
PopulateProperties(dataModelUIService);
if (DisplayViewModel == null)
return; return;
ListType = DisplayValue.GetType(); if (IsVisualizationExpanded && !DisplayViewModel.IsVisualizationExpanded)
PopulateProperties(dataModelUIService); DisplayViewModel.IsVisualizationExpanded = IsVisualizationExpanded;
foreach (DataModelVisualizationViewModel dataModelVisualizationViewModel in Children) DisplayViewModel.Update(dataModelUIService);
dataModelVisualizationViewModel.Update(dataModelUIService);
} }
public override object GetCurrentValue() public override object GetCurrentValue()

View File

@ -9,19 +9,17 @@ namespace Artemis.UI.Shared
private int _index; private int _index;
private Type _listType; private Type _listType;
public DataModelListPropertyViewModel(object listItem, DataModelDisplayViewModel displayViewModel) : base(null, null, null) public DataModelListPropertyViewModel(Type listType, DataModelDisplayViewModel displayViewModel) : base(null, null, null)
{ {
DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType()); DataModel = ListPredicateWrapperDataModel.Create(listType);
ListType = listItem.GetType(); ListType = listType;
DisplayValue = listItem;
DisplayViewModel = displayViewModel; DisplayViewModel = displayViewModel;
} }
public DataModelListPropertyViewModel(object listItem) : base(null, null, null) public DataModelListPropertyViewModel(Type listType) : base(null, null, null)
{ {
DataModel = ListPredicateWrapperDataModel.Create(listItem.GetType()); DataModel = ListPredicateWrapperDataModel.Create(listType);
ListType = listItem.GetType(); ListType = listType;
DisplayValue = listItem;
} }
public int Index public int Index
@ -47,6 +45,8 @@ namespace Artemis.UI.Shared
if (DisplayValue == null) if (DisplayValue == null)
return; return;
((ListPredicateWrapperDataModel)DataModel).UntypedValue = DisplayValue;
if (DisplayViewModel == null) if (DisplayViewModel == null)
DisplayViewModel = dataModelUIService.GetDataModelDisplayViewModel(DisplayValue.GetType(), true); DisplayViewModel = dataModelUIService.GetDataModelDisplayViewModel(DisplayValue.GetType(), true);

View File

@ -33,19 +33,19 @@ namespace Artemis.UI.Shared
public DataModelPropertiesViewModel GetListTypeViewModel(IDataModelUIService dataModelUIService) public DataModelPropertiesViewModel GetListTypeViewModel(IDataModelUIService dataModelUIService)
{ {
Type type = DataModelPath.GetPropertyType(); Type listType = DataModelPath.GetPropertyType()?.GenericTypeArguments[0];
if (type == null) if (listType == null)
return null; return null;
// Create a property VM describing the type of the list // Create a property VM describing the type of the list
DataModelVisualizationViewModel viewModel = CreateListChild(dataModelUIService, type.GenericTypeArguments[0]); DataModelVisualizationViewModel viewModel = CreateListChild(dataModelUIService, listType);
viewModel.Update(dataModelUIService);
// 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)
{ {
return dataModelListClassViewModel; return dataModelListClassViewModel;
} }
if (viewModel is DataModelListPropertyViewModel dataModelListPropertyViewModel) if (viewModel is DataModelListPropertyViewModel dataModelListPropertyViewModel)
{ {
dataModelListPropertyViewModel.DisplayValue = Activator.CreateInstance(dataModelListPropertyViewModel.ListType); dataModelListPropertyViewModel.DisplayValue = Activator.CreateInstance(dataModelListPropertyViewModel.ListType);
@ -67,12 +67,15 @@ namespace Artemis.UI.Shared
return; return;
int index = 0; int index = 0;
foreach (object? item in List) foreach (object item in List)
{ {
if (item == null)
continue;
DataModelVisualizationViewModel child; DataModelVisualizationViewModel child;
if (ListChildren.Count <= index) if (ListChildren.Count <= index)
{ {
child = CreateListChild(dataModelUIService, item); child = CreateListChild(dataModelUIService, item.GetType());
ListChildren.Add(child); ListChildren.Add(child);
} }
else else
@ -99,20 +102,18 @@ namespace Artemis.UI.Shared
Count = $"{ListChildren.Count} {(ListChildren.Count == 1 ? "item" : "items")}"; Count = $"{ListChildren.Count} {(ListChildren.Count == 1 ? "item" : "items")}";
} }
protected DataModelVisualizationViewModel CreateListChild(IDataModelUIService dataModelUIService, object listItem) protected DataModelVisualizationViewModel CreateListChild(IDataModelUIService dataModelUIService, Type listType)
{ {
Type listType = listItem.GetType();
// If a display VM was found, prefer to use that in any case // If a display VM was found, prefer to use that in any case
DataModelDisplayViewModel typeViewModel = dataModelUIService.GetDataModelDisplayViewModel(listType); DataModelDisplayViewModel typeViewModel = dataModelUIService.GetDataModelDisplayViewModel(listType);
if (typeViewModel != null) if (typeViewModel != null)
return new DataModelListPropertyViewModel(listItem, typeViewModel); return new DataModelListPropertyViewModel(listType, typeViewModel);
// For primitives, create a property view model, it may be null that is fine // For primitives, create a property view model, it may be null that is fine
if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string)) if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string))
return new DataModelListPropertyViewModel(listItem); return new DataModelListPropertyViewModel(listType);
// For other value types create a child view model // For other value types create a child view model
if (listType.IsClass || listType.IsStruct()) if (listType.IsClass || listType.IsStruct())
return new DataModelListPropertiesViewModel(listItem); return new DataModelListPropertiesViewModel(listType);
return null; return null;
} }

View File

@ -35,7 +35,7 @@ namespace Artemis.UI.Shared
PropertyDescription = DataModelPath?.GetPropertyDescription() ?? DataModel.DataModelDescription; PropertyDescription = DataModelPath?.GetPropertyDescription() ?? DataModel.DataModelDescription;
} }
public bool IsRootViewModel { get; } public bool IsRootViewModel { get; protected set; }
public DataModelPath DataModelPath { get; } public DataModelPath DataModelPath { get; }
public string Path => DataModelPath?.Path; public string Path => DataModelPath?.Path;
@ -81,7 +81,7 @@ namespace Artemis.UI.Shared
} }
} }
public virtual string DisplayPath => Path?.Replace(".", " "); public virtual string DisplayPath => string.Join(" ", DataModelPath.Segments.Select(s => s.GetPropertyDescription()?.Name ?? s.Identifier));
/// <summary> /// <summary>
/// Updates the datamodel and if in an parent, any children /// Updates the datamodel and if in an parent, any children
@ -146,7 +146,7 @@ namespace Artemis.UI.Shared
return null; return null;
if (propertyPath == null) if (propertyPath == null)
return null; return null;
if (Path.StartsWith(propertyPath, StringComparison.OrdinalIgnoreCase)) if (Path != null && Path.StartsWith(propertyPath, StringComparison.OrdinalIgnoreCase))
return null; return null;
} }
@ -183,7 +183,7 @@ namespace Artemis.UI.Shared
if (IsRootViewModel) if (IsRootViewModel)
return; return;
Type modelType = Parent.IsRootViewModel ? DataModel.GetType() : DataModelPath.GetPropertyType(); Type modelType = Parent == null || Parent.IsRootViewModel ? DataModel.GetType() : DataModelPath.GetPropertyType();
// Add missing static children // Add missing static children
foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) foreach (PropertyInfo propertyInfo in modelType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
@ -210,7 +210,7 @@ namespace Artemis.UI.Shared
} }
// Add missing dynamic children // Add missing dynamic children
object value = Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue(); object value = Parent == null || Parent.IsRootViewModel ? DataModel : DataModelPath.GetValue();
if (value is DataModel dataModel) if (value is DataModel dataModel)
{ {
foreach (KeyValuePair<string, DataModel> kvp in dataModel.DynamicDataModels) foreach (KeyValuePair<string, DataModel> kvp in dataModel.DynamicDataModels)

View File

@ -117,10 +117,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
if (!_isPrimitiveList) if (!_isPrimitiveList)
{ {
LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray(); // Lists use a different color
LeftSideSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(71, 108, 188)); LeftSideSelectionViewModel.ButtonBrush = new SolidColorBrush(Color.FromRgb(71, 108, 188));
LeftSideSelectionViewModel.SelectedPropertyViewModel = LeftSideSelectionViewModel.DataModelViewModel.GetChildByPath( LeftSideSelectionViewModel.FilterTypes = _supportedInputTypes.ToArray();
listDataModelGuid.Value, DataModelConditionListPredicate.DataModelConditionList.ListPath.Path LeftSideSelectionViewModel.PopulateSelectedPropertyViewModel(
DataModelConditionListPredicate.LeftPath?.Target,
DataModelConditionListPredicate.LeftPath?.Path
); );
} }
@ -141,9 +143,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
} }
// Ensure the right side has the proper VM // Ensure the right side has the proper VM
if ((DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic || ListRightSideType type = DataModelConditionListPredicate.PredicateType;
DataModelConditionListPredicate.PredicateType == ListRightSideType.DynamicList) && if ((type == ListRightSideType.Dynamic || type == ListRightSideType.DynamicList) && SelectedOperator.SupportsRightSide)
SelectedOperator.SupportsRightSide)
{ {
DisposeRightSideStatic(); DisposeRightSideStatic();
if (RightSideSelectionViewModel == null) if (RightSideSelectionViewModel == null)
@ -157,15 +158,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions
} }
RightSideSelectionViewModel.FilterTypes = new[] {leftSideType}; RightSideSelectionViewModel.FilterTypes = new[] {leftSideType};
if (DataModelConditionListPredicate.PredicateType == ListRightSideType.Dynamic) RightSideSelectionViewModel.PopulateSelectedPropertyViewModel(
RightSideSelectionViewModel.PopulateSelectedPropertyViewModel( DataModelConditionListPredicate.RightPath?.Target,
DataModelConditionListPredicate.RightPath?.Target, DataModelConditionListPredicate.RightPath?.Path
DataModelConditionListPredicate.RightPath?.Path );
);
else
RightSideSelectionViewModel.SelectedPropertyViewModel = RightSideSelectionViewModel.DataModelViewModel.GetChildByPath(
listDataModelGuid.Value, DataModelConditionListPredicate.RightPath?.Path
);
} }
else if (SelectedOperator.SupportsRightSide) else if (SelectedOperator.SupportsRightSide)
{ {

View File

@ -117,7 +117,7 @@
<ContentControl Grid.Column="2" s:View.Model="{Binding DisplayViewModel}" FontFamily="Consolas" /> <ContentControl Grid.Column="2" s:View.Model="{Binding DisplayViewModel}" FontFamily="Consolas" />
</Grid> </Grid>
</HierarchicalDataTemplate> </HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type dataModel:DataModelListPropertiesViewModel}" ItemsSource="{Binding Children}"> <HierarchicalDataTemplate DataType="{x:Type dataModel:DataModelListPropertiesViewModel}" ItemsSource="{Binding DisplayViewModel.Children}">
<TextBlock> <TextBlock>
<Run>List item [</Run><Run Text="{Binding Index, Mode=OneWay}" /><Run>]</Run> <Run>List item [</Run><Run Text="{Binding Index, Mode=OneWay}" /><Run>]</Run>
</TextBlock> </TextBlock>