From ae708fa26abf3e2702c70917d3c2954b30c98a64 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Tue, 11 Aug 2020 22:54:14 +0200 Subject: [PATCH] Display conditions - List predicates WIP --- .../Conditions/DisplayConditionGroup.cs | 4 + .../DisplayConditionListPredicate.cs | 21 ++--- .../Shared/DataModelListViewModel.cs | 25 +++++- .../Shared/DataModelVisualizationViewModel.cs | 4 +- .../ListDataModelWrapper.cs | 15 ++++ .../Services/DataModelVisualizationService.cs | 13 +++ .../DisplayConditions.xaml | 8 +- .../Abstract/DisplayConditionViewModel.cs | 9 +++ .../DisplayConditionGroupView.xaml | 6 +- .../DisplayConditionGroupViewModel.cs | 4 + .../DisplayConditionListPredicateView.xaml | 81 ++++++------------- .../DisplayConditionListPredicateViewModel.cs | 53 +++++++----- .../DisplayConditionPredicateView.xaml | 13 ++- .../DisplayConditionPredicateViewModel.cs | 1 + 14 files changed, 162 insertions(+), 95 deletions(-) create mode 100644 src/Artemis.UI.Shared/Services/DataModelVisualization/ListDataModelWrapper.cs diff --git a/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionGroup.cs b/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionGroup.cs index cbadd2967..e6d2591f7 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionGroup.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionGroup.cs @@ -37,6 +37,10 @@ namespace Artemis.Core.Models.Profile.Conditions public override bool Evaluate() { + // If there are less than two children, ignore the boolean operator + if (Children.Count <= 2) + return Children.All(c => c.Evaluate()); + switch (BooleanOperator) { case BooleanOperator.And: diff --git a/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionListPredicate.cs b/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionListPredicate.cs index 0f62eb0c4..b40560add 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionListPredicate.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DisplayConditionListPredicate.cs @@ -14,6 +14,9 @@ namespace Artemis.Core.Models.Profile.Conditions { Parent = parent; DisplayConditionListPredicateEntity = new DisplayConditionListPredicateEntity(); + + // There is always a child root group, add it + AddChild(new DisplayConditionGroup(this)); } public DisplayConditionListPredicate(DisplayConditionPart parent, DisplayConditionListPredicateEntity entity) @@ -22,15 +25,15 @@ namespace Artemis.Core.Models.Profile.Conditions DisplayConditionListPredicateEntity = entity; ListOperator = (ListOperator) entity.ListOperator; - foreach (var childEntity in DisplayConditionListPredicateEntity.Children) + // There should only be one child and it should be a group + var rootGroup = DisplayConditionListPredicateEntity.Children.SingleOrDefault() as DisplayConditionGroupEntity; + if (rootGroup == null) { - if (childEntity is DisplayConditionGroupEntity groupEntity) - AddChild(new DisplayConditionGroup(this, groupEntity)); - else if (childEntity is DisplayConditionPredicateEntity predicateEntity) - AddChild(new DisplayConditionPredicate(this, predicateEntity)); - else if (childEntity is DisplayConditionListPredicateEntity listPredicateEntity) - AddChild(new DisplayConditionListPredicate(this, listPredicateEntity)); + DisplayConditionListPredicateEntity.Children.Clear(); + AddChild(new DisplayConditionGroup(this)); } + else + AddChild(new DisplayConditionGroup(this, rootGroup)); } public DisplayConditionListPredicateEntity DisplayConditionListPredicateEntity { get; set; } @@ -76,8 +79,8 @@ namespace Artemis.Core.Models.Profile.Conditions } // Children - foreach (var child in Children) - child.Initialize(dataModelService); + var rootGroup = (DisplayConditionGroup) Children.Single(); + rootGroup.Initialize(dataModelService); } public void UpdateList(DataModel dataModel, string path) diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs index 1ef1f51ba..4807135fb 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs @@ -13,6 +13,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared { private string _count; private IList _list; + private DataModelVisualizationViewModel _listTypePropertyViewModel; internal DataModelListViewModel(DataModel dataModel, DataModelVisualizationViewModel parent, PropertyInfo propertyInfo) : base(dataModel, parent, propertyInfo) { @@ -25,6 +26,12 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared set => SetAndNotify(ref _list, value); } + public DataModelVisualizationViewModel ListTypePropertyViewModel + { + get => _listTypePropertyViewModel; + set => SetAndNotify(ref _listTypePropertyViewModel, value); + } + public BindableCollection ListChildren { get; set; } public string Count @@ -42,6 +49,20 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared if (List == null) return; + if (ListTypePropertyViewModel == null) + { + // Create a property VM describing the type of the list + ListTypePropertyViewModel = CreateListChild(dataModelVisualizationService, List.GetType().GenericTypeArguments[0]); + + // Put an empty value into the list type property view model + if (ListTypePropertyViewModel is DataModelListPropertiesViewModel dataModelListClassViewModel) + dataModelListClassViewModel.DisplayValue = Activator.CreateInstance(dataModelListClassViewModel.ListType); + else if (ListTypePropertyViewModel is DataModelListPropertyViewModel dataModelListPropertyViewModel) + dataModelListPropertyViewModel.DisplayValue = Activator.CreateInstance(dataModelListPropertyViewModel.ListType); + + ListTypePropertyViewModel.Update(dataModelVisualizationService); + } + var index = 0; foreach (var item in List) { @@ -83,10 +104,10 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared return new DataModelListPropertyViewModel(DataModel, this, PropertyInfo) {DisplayViewModel = typeViewModel}; // For primitives, create a property view model, it may be null that is fine if (listType.IsPrimitive || listType == typeof(string)) - return new DataModelListPropertyViewModel(DataModel, this, PropertyInfo); + return new DataModelListPropertyViewModel(DataModel, this, PropertyInfo) {ListType = listType}; // For other value types create a child view model if (listType.IsClass || listType.IsStruct()) - return new DataModelListPropertiesViewModel(DataModel, this, PropertyInfo); + return new DataModelListPropertiesViewModel(DataModel, this, PropertyInfo) {ListType = listType}; return null; } diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs index 25bede591..b31edb00a 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs @@ -35,7 +35,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared Parent = parent; Children = new BindableCollection(); IsMatchingFilteredTypes = true; - + if (dataModel == null && parent == null && propertyInfo == null) IsRootViewModel = true; else @@ -176,7 +176,7 @@ namespace Artemis.UI.Shared.DataModelVisualization.Shared IsMatchingFilteredTypes = false; return; } - + if (looseMatch) IsMatchingFilteredTypes = filteredTypes.Any(t => t.IsCastableFrom(PropertyInfo.PropertyType)); else diff --git a/src/Artemis.UI.Shared/Services/DataModelVisualization/ListDataModelWrapper.cs b/src/Artemis.UI.Shared/Services/DataModelVisualization/ListDataModelWrapper.cs new file mode 100644 index 000000000..9123edeee --- /dev/null +++ b/src/Artemis.UI.Shared/Services/DataModelVisualization/ListDataModelWrapper.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Artemis.Core.Plugins.Abstract.DataModels; + +namespace Artemis.UI.Shared.Services.DataModelVisualization +{ + public class ListDataModelWrapper : DataModel + { + public ListDataModelWrapper() + { + + } + } +} diff --git a/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs b/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs index 3c20dad59..482720f00 100644 --- a/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs +++ b/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using Artemis.Core.Extensions; @@ -9,6 +10,7 @@ using Artemis.Core.Plugins.Models; using Artemis.Core.Services.Interfaces; using Artemis.UI.Shared.DataModelVisualization; using Artemis.UI.Shared.DataModelVisualization.Shared; +using Artemis.UI.Shared.Services.DataModelVisualization; using Artemis.UI.Shared.Services.Interfaces; using Ninject; using Ninject.Parameters; @@ -61,6 +63,17 @@ namespace Artemis.UI.Shared.Services return viewModel; } + // public DataModelPropertiesViewModel GetListDataModelVisualization(IList list) + // { + // var viewModel = new DataModelPropertiesViewModel(null, null, null); + // viewModel.Children.Add(new DataModelListPropertiesViewModel(null, viewModel, null) {DisplayValue = list}); + // + // // Update to populate children + // viewModel.Update(this); + // viewModel.UpdateRequested += (sender, args) => viewModel.Update(this); + // return viewModel; + // } + public bool GetPluginExtendsDataModel(Plugin plugin) { return _dataModelService.GetPluginExtendsDataModel(plugin); diff --git a/src/Artemis.UI/ResourceDictionaries/DisplayConditions.xaml b/src/Artemis.UI/ResourceDictionaries/DisplayConditions.xaml index 78037d7e0..fb6938622 100644 --- a/src/Artemis.UI/ResourceDictionaries/DisplayConditions.xaml +++ b/src/Artemis.UI/ResourceDictionaries/DisplayConditions.xaml @@ -27,7 +27,7 @@ - + @@ -48,9 +48,9 @@ - + - + @@ -96,5 +96,5 @@ - + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/Abstract/DisplayConditionViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/Abstract/DisplayConditionViewModel.cs index cdac16aab..73faf848c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/Abstract/DisplayConditionViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/Abstract/DisplayConditionViewModel.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using Artemis.Core.Models.Profile.Conditions.Abstract; +using Artemis.UI.Shared.DataModelVisualization.Shared; using Stylet; namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions.Abstract @@ -28,6 +30,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions.Abstract public abstract void Update(); + public virtual List GetExtraDataModels() + { + if (Parent != null) + return Parent.GetExtraDataModels(); + return new List(); + } + public virtual void Delete() { Model.Parent.RemoveChild(Model); diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupView.xaml index 04662aa84..21180d338 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupView.xaml @@ -29,6 +29,7 @@ - + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionListPredicateViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionListPredicateViewModel.cs index f01d80f91..c3e946958 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionListPredicateViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionListPredicateViewModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Timers; @@ -22,7 +23,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions private readonly IDataModelVisualizationService _dataModelVisualizationService; private readonly IDisplayConditionsVmFactory _displayConditionsVmFactory; private bool _isInitialized; - private DataModelVisualizationViewModel _selectedListProperty; + private DataModelListViewModel _selectedListProperty; private DataModelPropertiesViewModel _targetDataModel; private readonly Timer _updateTimer; @@ -66,7 +67,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions set => SetAndNotify(ref _targetDataModel, value); } - public DataModelVisualizationViewModel SelectedListProperty + public DataModelListViewModel SelectedListProperty { get => _selectedListProperty; set => SetAndNotify(ref _selectedListProperty, value); @@ -132,12 +133,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e) { if (TargetDataModelOpen) - TargetDataModel.Update(_dataModelVisualizationService); + { + TargetDataModel?.Update(_dataModelVisualizationService); + SelectedListProperty?.Update(_dataModelVisualizationService); + } } private void TargetDataModelUpdateRequested(object sender, EventArgs e) { - TargetDataModel.ApplyTypeFilter(true, typeof(IEnumerable)); + TargetDataModel.ApplyTypeFilter(true, typeof(IList)); } public void ApplyList() @@ -148,6 +152,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions Update(); } + public override List GetExtraDataModels() + { + var list = base.GetExtraDataModels(); + if (SelectedListProperty != null) + list.Add(SelectedListProperty.ListTypePropertyViewModel); + + return list; + } + public override void Update() { if (TargetDataModel == null) @@ -157,9 +170,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions // Update the selected list property if (DisplayConditionListPredicate.ListDataModel != null && DisplayConditionListPredicate.ListPropertyPath != null) - SelectedListProperty = TargetDataModel.GetChildByPath(DisplayConditionListPredicate.ListDataModel.PluginInfo.Guid, DisplayConditionListPredicate.ListPropertyPath); + { + var child = TargetDataModel.GetChildByPath(DisplayConditionListPredicate.ListDataModel.PluginInfo.Guid, DisplayConditionListPredicate.ListPropertyPath); + SelectedListProperty = child as DataModelListViewModel; + } + // Ensure filtering is applied to include Enumerables only - TargetDataModel.ApplyTypeFilter(true, typeof(IEnumerable)); + TargetDataModel.ApplyTypeFilter(true, typeof(IList)); // Remove VMs of effects no longer applied on the layer var toRemove = Children.Where(c => !DisplayConditionListPredicate.Children.Contains(c.Model)).ToList(); @@ -174,19 +191,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions { if (Children.Any(c => c.Model == childModel)) continue; + if (!(childModel is DisplayConditionGroup displayConditionGroup)) + continue; - switch (childModel) - { - case DisplayConditionGroup displayConditionGroup: - Children.Add(_displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this)); - break; - case DisplayConditionListPredicate displayConditionListPredicate: - Children.Add(_displayConditionsVmFactory.DisplayConditionListPredicateViewModel(displayConditionListPredicate, this)); - break; - case DisplayConditionPredicate displayConditionPredicate: - Children.Add(_displayConditionsVmFactory.DisplayConditionPredicateViewModel(displayConditionPredicate, this)); - break; - } + var viewModel = _displayConditionsVmFactory.DisplayConditionGroupViewModel(displayConditionGroup, this); + viewModel.IsRootGroup = true; + Children.Add(viewModel); } foreach (var childViewModel in Children) @@ -196,10 +206,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions private void ExecuteSelectListProperty(object context) { - if (!(context is DataModelVisualizationViewModel dataModelVisualizationViewModel)) + if (!(context is DataModelListViewModel dataModelListViewModel)) return; - SelectedListProperty = dataModelVisualizationViewModel; + SelectedListProperty = dataModelListViewModel; + if (SelectedListProperty.ListTypePropertyViewModel == null) + SelectedListProperty.Update(_dataModelVisualizationService); + ApplyList(); } } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateView.xaml index faeab871a..a289bf599 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateView.xaml +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateView.xaml @@ -21,6 +21,14 @@ + + + + + + + + @@ -34,6 +42,7 @@