From 4034f438edca95cc86dfb818b34cd0a6e5ec8c02 Mon Sep 17 00:00:00 2001 From: Robert Date: Tue, 6 Jul 2021 23:45:34 +0200 Subject: [PATCH 1/2] UI - Fix possible exception when showing dialogs Profile editor - Limit undo/redo to 20 actions for now Plugins - Fix custom icons not displaying in settings windows --- src/Artemis.Core/Models/Profile/Profile.cs | 8 +- .../Services/Storage/ProfileService.cs | 4 +- src/Artemis.Core/Utilities/MaxStack.cs | 118 ++++++++++++++++++ .../Services/Dialog/DialogService.cs | 2 +- .../Plugins/PluginSettingsWindowView.xaml | 9 +- .../Plugins/PluginSettingsWindowViewModel.cs | 5 +- .../Services/DeviceLayoutService.cs | 10 +- 7 files changed, 143 insertions(+), 13 deletions(-) create mode 100644 src/Artemis.Core/Utilities/MaxStack.cs diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index e2870dec1..a018b947a 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -25,8 +25,8 @@ namespace Artemis.Core Scripts = new List(); ScriptConfigurations = new List(); - UndoStack = new Stack(); - RedoStack = new Stack(); + UndoStack = new MaxStack(20); + RedoStack = new MaxStack(20); Load(); } @@ -75,8 +75,8 @@ namespace Artemis.Core /// public ProfileEntity ProfileEntity { get; internal set; } - internal Stack UndoStack { get; set; } - internal Stack RedoStack { get; set; } + internal MaxStack UndoStack { get; set; } + internal MaxStack RedoStack { get; set; } /// public override void Update(double deltaTime) diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index 5cdf00f06..63d17ee67 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -470,7 +470,7 @@ namespace Artemis.Core.Services // Keep the profile from being rendered by locking it lock (profile) { - if (!profile.UndoStack.Any()) + if (profile.UndoStack.Count == 0) { _logger.Debug("Undo profile update - Failed, undo stack empty"); return false; @@ -496,7 +496,7 @@ namespace Artemis.Core.Services // Keep the profile from being rendered by locking it lock (profile) { - if (!profile.RedoStack.Any()) + if (profile.RedoStack.Count == 0) { _logger.Debug("Redo profile update - Failed, redo empty"); return false; diff --git a/src/Artemis.Core/Utilities/MaxStack.cs b/src/Artemis.Core/Utilities/MaxStack.cs new file mode 100644 index 000000000..8767522d2 --- /dev/null +++ b/src/Artemis.Core/Utilities/MaxStack.cs @@ -0,0 +1,118 @@ +// Source: https://ntsblog.homedev.com.au/index.php/2010/05/06/c-stack-with-maximum-limit/ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Artemis.Core +{ + /// + /// Generic stack implementation with a maximum limit + /// When something is pushed on the last item is removed from the list + /// + [Serializable] + internal class MaxStack + { + #region Fields + + private int _limit; + private LinkedList _list; + + #endregion + + #region Constructors + + public MaxStack(int maxSize) + { + _limit = maxSize; + _list = new LinkedList(); + + } + + #endregion + + #region Public Stack Implementation + + public void Push(T value) + { + if (_list.Count == _limit) + { + _list.RemoveLast(); + } + _list.AddFirst(value); + } + + public T Pop() + { + if (_list.Count > 0) + { + T value = _list.First.Value; + _list.RemoveFirst(); + return value; + } + else + { + throw new InvalidOperationException("The Stack is empty"); + } + + + } + + public T Peek() + { + if (_list.Count > 0) + { + T value = _list.First.Value; + return value; + } + else + { + throw new InvalidOperationException("The Stack is empty"); + } + + } + + public void Clear() + { + _list.Clear(); + + } + + public int Count + { + get { return _list.Count; } + } + + /// + /// Checks if the top object on the stack matches the value passed in + /// + /// + /// + public bool IsTop(T value) + { + bool result = false; + if (this.Count > 0) + { + result = Peek().Equals(value); + } + return result; + } + + public bool Contains(T value) + { + bool result = false; + if (this.Count > 0) + { + result = _list.Contains(value); + } + return result; + } + + public IEnumerator GetEnumerator() + { + return _list.GetEnumerator(); + } + + #endregion + + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Services/Dialog/DialogService.cs b/src/Artemis.UI.Shared/Services/Dialog/DialogService.cs index e3d26e577..dcfe3b9d6 100644 --- a/src/Artemis.UI.Shared/Services/Dialog/DialogService.cs +++ b/src/Artemis.UI.Shared/Services/Dialog/DialogService.cs @@ -122,7 +122,7 @@ namespace Artemis.UI.Shared.Services public void ShowExceptionDialog(string message, Exception exception) { if (exception == null) throw new ArgumentNullException(nameof(exception)); - _windowManager.ShowDialog(new ExceptionViewModel(message, exception)); + Execute.OnUIThread(() => _windowManager.ShowDialog(new ExceptionViewModel(message, exception))); } private IKernel GetBestKernel() diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml index ad7623595..1500833d6 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml +++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowView.xaml @@ -26,7 +26,14 @@ - + diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowViewModel.cs index 47230b878..748713f48 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsWindowViewModel.cs @@ -1,4 +1,5 @@ using System; +using Artemis.Core; using Artemis.UI.Shared; using Stylet; @@ -11,10 +12,10 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins public PluginSettingsWindowViewModel(PluginConfigurationViewModel configurationViewModel) { _configurationViewModel = configurationViewModel ?? throw new ArgumentNullException(nameof(configurationViewModel)); - Icon = configurationViewModel.Plugin.Info.Icon; + Plugin = configurationViewModel.Plugin; } - public object Icon { get; } + public Plugin Plugin { get; } protected override void OnInitialActivate() { diff --git a/src/Artemis.UI/Services/DeviceLayoutService.cs b/src/Artemis.UI/Services/DeviceLayoutService.cs index 536763729..f15dcaca8 100644 --- a/src/Artemis.UI/Services/DeviceLayoutService.cs +++ b/src/Artemis.UI/Services/DeviceLayoutService.cs @@ -8,6 +8,7 @@ using Artemis.UI.Screens.Settings.Device; using Artemis.UI.Shared.Services; using MaterialDesignThemes.Wpf; using RGB.NET.Core; +using Stylet; using KeyboardLayoutType = Artemis.Core.KeyboardLayoutType; namespace Artemis.UI.Services @@ -62,8 +63,11 @@ namespace Artemis.UI.Services private async void WindowServiceOnMainWindowOpened(object sender, EventArgs e) { List devices = _rgbService.Devices.Where(device => DeviceNeedsLayout(device) && !_ignoredDevices.Contains(device)).ToList(); - foreach (ArtemisDevice artemisDevice in devices) - await RequestLayoutInput(artemisDevice); + await Execute.OnUIThreadAsync(async () => + { + foreach (ArtemisDevice artemisDevice in devices) + await RequestLayoutInput(artemisDevice); + }); } private async void RgbServiceOnDeviceAdded(object sender, DeviceEventArgs e) @@ -77,7 +81,7 @@ namespace Artemis.UI.Services return; } - await RequestLayoutInput(e.Device); + await Execute.OnUIThreadAsync(async () => await RequestLayoutInput(e.Device)); } #endregion From 4fe0ea38cb819669d9c62165db3b05705ad728bd Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 8 Jul 2021 19:02:06 +0200 Subject: [PATCH 2/2] Modules - Added ListItemName prop to the DataModelProperty attribute Conditions - Display the full path of a condition (can be disabled in the editor options menu) Hotkeys - Fixed hotkeys not working after restarting Artemis Profile editor - Fixed display conditions not showing last selected layer on editor open --- .../DataModelConditionListPredicate.cs | 11 +++++-- .../Wrappers/ListPredicateWrapperDataModel.cs | 31 +++++++++++++++---- .../Profile/DataModel/DataModelPathSegment.cs | 4 +-- .../Modules/Attributes/DataModelProperty.cs | 5 +++ src/Artemis.Core/Plugins/Modules/DataModel.cs | 9 ++++++ .../Services/Storage/ProfileService.cs | 1 + .../Input/DataModelDynamicViewModel.cs | 27 ++++++++++++++-- .../DataModelListPropertiesViewModel.cs | 4 +-- .../Shared/DataModelListPropertyViewModel.cs | 8 ++--- .../Shared/DataModelListViewModel.cs | 10 +++--- ...ataModelConditionListPredicateViewModel.cs | 8 +++-- .../DisplayConditionsViewModel.cs | 20 +++++++----- .../ProfileEditor/ProfileEditorView.xaml | 4 ++- .../ProfileEditor/ProfileEditorViewModel.cs | 3 ++ .../Dialogs/ProfileEdit/ProfileEditView.xaml | 2 +- 15 files changed, 111 insertions(+), 36 deletions(-) diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionListPredicate.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionListPredicate.cs index b5439c2bf..5fdc3a8d8 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionListPredicate.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionListPredicate.cs @@ -1,4 +1,5 @@ using System; +using Artemis.Core.Modules; using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile.Conditions; @@ -69,7 +70,10 @@ namespace Artemis.Core { if (Entity.LeftPath != null) LeftPath = DataModelConditionList.ListType != null - ? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), Entity.LeftPath) + ? new DataModelPath(ListPredicateWrapperDataModel.Create( + DataModelConditionList.ListType, + DataModelConditionList.ListPath?.GetPropertyDescription()?.ListItemName + ), Entity.LeftPath) : null; } @@ -82,7 +86,10 @@ namespace Artemis.Core if (Entity.RightPath.WrapperType == PathWrapperType.List) { RightPath = DataModelConditionList.ListType != null - ? new DataModelPath(ListPredicateWrapperDataModel.Create(DataModelConditionList.ListType), Entity.RightPath) + ? new DataModelPath(ListPredicateWrapperDataModel.Create( + DataModelConditionList.ListType, + DataModelConditionList.ListPath?.GetPropertyDescription()?.ListItemName + ), Entity.RightPath) : null; } // Right side dynamic diff --git a/src/Artemis.Core/Models/Profile/Conditions/Wrappers/ListPredicateWrapperDataModel.cs b/src/Artemis.Core/Models/Profile/Conditions/Wrappers/ListPredicateWrapperDataModel.cs index 05b3e598e..69a2fe087 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/Wrappers/ListPredicateWrapperDataModel.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/Wrappers/ListPredicateWrapperDataModel.cs @@ -1,11 +1,11 @@ using System; +using System.Reflection; using Artemis.Core.Modules; namespace Artemis.Core { internal class ListPredicateWrapperDataModel : ListPredicateWrapperDataModel { - [DataModelProperty(Name = "List item", Description = "The current item in the list")] public T Value => (UntypedValue is T typedValue ? typedValue : default)!; } @@ -26,15 +26,34 @@ namespace Artemis.Core public object? UntypedValue { get; set; } /// - /// Creates a new instance of the class + /// Gets or sets the name of the list item /// - public static ListPredicateWrapperDataModel Create(Type type) + [DataModelIgnore] + public string? ItemName { get; set; } + + #region Overrides of DataModel + + /// + public override DataModelPropertyAttribute? GetPropertyDescription(PropertyInfo propertyInfo) { - object? instance = Activator.CreateInstance(typeof(ListPredicateWrapperDataModel<>).MakeGenericType(type)); + if (!string.IsNullOrWhiteSpace(ItemName)) + return new DataModelPropertyAttribute {Name = ItemName}; + return base.GetPropertyDescription(propertyInfo); + } + + #endregion + + /// + /// Creates a new instance of the class + /// + public static ListPredicateWrapperDataModel Create(Type type, string? name = null) + { + ListPredicateWrapperDataModel? instance = Activator.CreateInstance(typeof(ListPredicateWrapperDataModel<>).MakeGenericType(type)) as ListPredicateWrapperDataModel; if (instance == null) throw new ArtemisCoreException($"Failed to create an instance of ListPredicateWrapperDataModel for type {type.Name}"); - - return (ListPredicateWrapperDataModel) instance; + + instance.ItemName = name; + return instance; } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs index 9e5be4a9e..5c70eae3f 100644 --- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPathSegment.cs @@ -122,7 +122,7 @@ namespace Artemis.Core return null; // Static types may have one as an attribute - DataModelPropertyAttribute? attribute = (DataModelPropertyAttribute?) Attribute.GetCustomAttribute(propertyInfo, typeof(DataModelPropertyAttribute)); + DataModelPropertyAttribute? attribute = DataModelPath.Target?.GetPropertyDescription(propertyInfo); if (attribute != null) { if (string.IsNullOrWhiteSpace(attribute.Name)) @@ -211,7 +211,7 @@ namespace Artemis.Core // A static segment just needs to access the property or filed else if (Type == DataModelPathSegmentType.Static) { - accessorExpression = _property != null + accessorExpression = _property != null ? Expression.Property(expression, _property) : Expression.PropertyOrField(expression, Identifier); } diff --git a/src/Artemis.Core/Plugins/Modules/Attributes/DataModelProperty.cs b/src/Artemis.Core/Plugins/Modules/Attributes/DataModelProperty.cs index 11fe2993f..1b7793f2d 100644 --- a/src/Artemis.Core/Plugins/Modules/Attributes/DataModelProperty.cs +++ b/src/Artemis.Core/Plugins/Modules/Attributes/DataModelProperty.cs @@ -28,6 +28,11 @@ namespace Artemis.Core.Modules /// public string? Affix { get; set; } + /// + /// Gets or sets the name of list items, only applicable to enumerable data model properties + /// + public string? ListItemName { get; set; } + /// /// Gets or sets an optional maximum value, this value is not enforced but used for percentage calculations. /// diff --git a/src/Artemis.Core/Plugins/Modules/DataModel.cs b/src/Artemis.Core/Plugins/Modules/DataModel.cs index d6730df88..c2eb187c9 100644 --- a/src/Artemis.Core/Plugins/Modules/DataModel.cs +++ b/src/Artemis.Core/Plugins/Modules/DataModel.cs @@ -69,6 +69,15 @@ namespace Artemis.Core.Modules return Module.HiddenProperties; } + /// + /// Gets the property description of the provided property info + /// + /// If found, the property description attribute, otherwise . + public virtual DataModelPropertyAttribute? GetPropertyDescription(PropertyInfo propertyInfo) + { + return (DataModelPropertyAttribute?) Attribute.GetCustomAttribute(propertyInfo, typeof(DataModelPropertyAttribute)); + } + #region Dynamic children /// diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index 63d17ee67..16e737689 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -49,6 +49,7 @@ namespace Artemis.Core.Services _pluginManagementService.PluginFeatureEnabled += PluginManagementServiceOnPluginFeatureToggled; _pluginManagementService.PluginFeatureDisabled += PluginManagementServiceOnPluginFeatureToggled; + HotkeysEnabled = true; inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp; if (!_profileCategories.Any()) diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs index ad6697b92..ad9b65584 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Input/DataModelDynamicViewModel.cs @@ -30,12 +30,14 @@ namespace Artemis.UI.Shared.Input private bool _isDataModelViewModelOpen; private bool _isEnabled = true; private string _placeholder = "Select a property"; + private readonly PluginSetting _showFullPath; internal DataModelDynamicViewModel(List modules, ISettingsService settingsService, IDataModelUIService dataModelUIService) { _modules = modules; _dataModelUIService = dataModelUIService; _updateTimer = new Timer(500); + _showFullPath = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true); ExtraDataModelViewModels = new BindableCollection(); ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues"); @@ -127,6 +129,8 @@ namespace Artemis.UI.Shared.Input /// public PluginSetting ShowDataModelValues { get; } + public PluginSetting ShowFullPath { get; } + /// /// Gets or sets root the data model view model /// @@ -177,7 +181,15 @@ namespace Artemis.UI.Shared.Input /// /// Gets the display name of the currently selected property /// - public string? DisplayValue => DataModelPath?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier; + public string? DisplayValue + { + get + { + if (_showFullPath.Value) + return DisplayPath; + return DataModelPath?.GetPropertyDescription()?.Name ?? DataModelPath?.Segments.LastOrDefault()?.Identifier; + } + } /// /// Gets the human readable path of the currently selected property @@ -190,7 +202,8 @@ namespace Artemis.UI.Shared.Input return "Click to select a property"; if (!DataModelPath.IsValid) return "Invalid path"; - return string.Join(" › ", DataModelPath.Segments.Select(s => s.GetPropertyDescription()?.Name ?? s.Identifier)); + + return string.Join(" › ", DataModelPath.Segments.Where(s => s.GetPropertyDescription()!= null).Select(s => s.GetPropertyDescription()!.Name)); } } @@ -244,8 +257,10 @@ namespace Artemis.UI.Shared.Input ExtraDataModelViewModels.CollectionChanged += ExtraDataModelViewModelsOnCollectionChanged; _updateTimer.Start(); _updateTimer.Elapsed += OnUpdateTimerOnElapsed; + _showFullPath.SettingChanged += ShowFullPathOnSettingChanged; } + private void ExecuteSelectPropertyCommand(object? context) { if (context is not DataModelVisualizationViewModel selected) @@ -271,7 +286,8 @@ namespace Artemis.UI.Shared.Input _updateTimer.Stop(); _updateTimer.Dispose(); _updateTimer.Elapsed -= OnUpdateTimerOnElapsed; - + _showFullPath.SettingChanged -= ShowFullPathOnSettingChanged; + DataModelViewModel?.Dispose(); DataModelPath?.Dispose(); } @@ -330,6 +346,11 @@ namespace Artemis.UI.Shared.Input } } + private void ShowFullPathOnSettingChanged(object? sender, EventArgs e) + { + NotifyOfPropertyChange(nameof(DisplayValue)); + } + #endregion #region Events diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs index 56cd17a83..bbc85258a 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertiesViewModel.cs @@ -16,9 +16,9 @@ namespace Artemis.UI.Shared private int _index; private Type? _listType; - internal DataModelListPropertiesViewModel(Type listType) : base(null, null, null) + internal DataModelListPropertiesViewModel(Type listType, string? name) : base(null, null, null) { - _listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType); + _listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType, name); DataModel = _listPredicateWrapper; ListType = listType; } diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs index cf5bed3c8..2e3c7fe32 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListPropertyViewModel.cs @@ -14,17 +14,17 @@ namespace Artemis.UI.Shared private int _index; private Type? _listType; - internal DataModelListPropertyViewModel(Type listType, DataModelDisplayViewModel displayViewModel) : base(null, null, null) + internal DataModelListPropertyViewModel(Type listType, DataModelDisplayViewModel displayViewModel, string? name) : base(null, null, null) { - _listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType); + _listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType, name); DataModel = _listPredicateWrapper; ListType = listType; DisplayViewModel = displayViewModel; } - internal DataModelListPropertyViewModel(Type listType) : base(null, null, null) + internal DataModelListPropertyViewModel(Type listType, string? name) : base(null, null, null) { - _listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType); + _listPredicateWrapper = ListPredicateWrapperDataModel.Create(listType, name); DataModel = _listPredicateWrapper; ListType = listType; } diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs index 09187f910..3605c43a0 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs @@ -91,7 +91,7 @@ namespace Artemis.UI.Shared DataModelVisualizationViewModel? child; if (ListChildren.Count <= index) { - child = CreateListChild(dataModelUIService, item.GetType()); + child = CreateListChild(dataModelUIService, item.GetType(), DataModelPath?.GetPropertyDescription()?.ListItemName); if (child == null) continue; ListChildren.Add(child); @@ -130,18 +130,18 @@ namespace Artemis.UI.Shared return $"[List] {DisplayPath ?? Path} - {ListCount} item(s)"; } - private DataModelVisualizationViewModel? CreateListChild(IDataModelUIService dataModelUIService, Type listType) + private DataModelVisualizationViewModel? CreateListChild(IDataModelUIService dataModelUIService, Type listType, string? name) { // If a display VM was found, prefer to use that in any case DataModelDisplayViewModel? typeViewModel = dataModelUIService.GetDataModelDisplayViewModel(listType, PropertyDescription); if (typeViewModel != null) - return new DataModelListPropertyViewModel(listType, typeViewModel); + return new DataModelListPropertyViewModel(listType, typeViewModel, name); // For primitives, create a property view model, it may be null that is fine if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string)) - return new DataModelListPropertyViewModel(listType); + return new DataModelListPropertyViewModel(listType, name); // For other value types create a child view model if (listType.IsClass || listType.IsStruct()) - return new DataModelListPropertiesViewModel(listType); + return new DataModelListPropertiesViewModel(listType, name); return null; } diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/Predicate/DataModelConditionListPredicateViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Conditions/Predicate/DataModelConditionListPredicateViewModel.cs index 1a9f947b5..774a10a73 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Conditions/Predicate/DataModelConditionListPredicateViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/Predicate/DataModelConditionListPredicateViewModel.cs @@ -24,7 +24,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions : base(dataModelConditionListPredicate, modules, profileEditorService, dataModelUIService, conditionOperatorService, settingsService) { _dataModelUIService = dataModelUIService; - + DataModelPathSegment dataModelPathSegment = dataModelConditionListPredicate.LeftPath.Segments.ToList()[1]; + var segmentDescription = dataModelPathSegment.GetPropertyDescription(); LeftSideColor = new SolidColorBrush(Color.FromRgb(71, 108, 188)); } @@ -47,7 +48,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions public override void Evaluate() { - throw new NotImplementedException(); + } public override void UpdateModules() @@ -88,7 +89,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Conditions private DataModelPropertiesViewModel GetListDataModel() { ListPredicateWrapperDataModel wrapper = ListPredicateWrapperDataModel.Create( - DataModelConditionListPredicate.DataModelConditionList.ListType + DataModelConditionListPredicate.DataModelConditionList.ListType!, + DataModelConditionListPredicate.DataModelConditionList.ListPath?.GetPropertyDescription()?.ListItemName ); return wrapper.CreateViewModel(_dataModelUIService, new DataModelUpdateConfiguration(true)); diff --git a/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs index f76a49252..fad56c3dc 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs @@ -4,7 +4,6 @@ using System.ComponentModel; using System.Linq; using Artemis.Core; using Artemis.Core.Modules; -using Artemis.Core.Services; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.ProfileEditor.Conditions; using Artemis.UI.Shared; @@ -91,6 +90,8 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions protected override void OnInitialActivate() { _profileEditorService.SelectedProfileElementChanged += SelectedProfileEditorServiceOnSelectedProfileElementChanged; + Update(_profileEditorService.SelectedProfileElement); + base.OnInitialActivate(); } @@ -101,6 +102,11 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions } private void SelectedProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e) + { + Update(e.RenderProfileElement); + } + + private void Update(RenderProfileElement renderProfileElement) { if (RenderProfileElement != null) { @@ -109,26 +115,26 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions RenderProfileElement.Timeline.PropertyChanged -= TimelineOnPropertyChanged; } - RenderProfileElement = e.RenderProfileElement; + RenderProfileElement = renderProfileElement; NotifyOfPropertyChange(nameof(DisplayContinuously)); NotifyOfPropertyChange(nameof(AlwaysFinishTimeline)); NotifyOfPropertyChange(nameof(ConditionBehaviourEnabled)); - if (e.RenderProfileElement == null) + if (renderProfileElement == null) { ActiveItem = null; return; } // Ensure the layer has a root display condition group - if (e.RenderProfileElement.DisplayCondition == null) - e.RenderProfileElement.DisplayCondition = new DataModelConditionGroup(null); + if (renderProfileElement.DisplayCondition == null) + renderProfileElement.DisplayCondition = new DataModelConditionGroup(null); List modules = new(); if (_profileEditorService.SelectedProfileConfiguration?.Module != null) modules.Add(_profileEditorService.SelectedProfileConfiguration.Module); - ActiveItem = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(e.RenderProfileElement.DisplayCondition, ConditionGroupType.General, modules); + ActiveItem = _dataModelConditionsVmFactory.DataModelConditionGroupViewModel(renderProfileElement.DisplayCondition, ConditionGroupType.General, modules); ActiveItem.IsRootGroup = true; DisplayStartHint = !RenderProfileElement.DisplayCondition.Children.Any(); @@ -138,7 +144,7 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions RenderProfileElement.DisplayCondition.ChildRemoved += DisplayConditionOnChildrenModified; RenderProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged; } - + private void TimelineOnPropertyChanged(object sender, PropertyChangedEventArgs e) { NotifyOfPropertyChange(nameof(DisplayContinuously)); diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.xaml b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.xaml index b7eb9c767..c7cf110cf 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorView.xaml @@ -122,7 +122,9 @@ - + ElementPropertiesWidth => _settingsService.GetSetting("ProfileEditor.ElementPropertiesWidth", new GridLength(545)); public PluginSetting StopOnFocusLoss => _settingsService.GetSetting("ProfileEditor.StopOnFocusLoss", true); public PluginSetting ShowDataModelValues => _settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false); + public PluginSetting ShowFullPaths => _settingsService.GetSetting("ProfileEditor.ShowFullPaths", true); public PluginSetting FocusSelectedLayer => _settingsService.GetSetting("ProfileEditor.FocusSelectedLayer", true); public PluginSetting AlwaysApplyDataBindings => _settingsService.GetSetting("ProfileEditor.AlwaysApplyDataBindings", true); @@ -192,6 +193,7 @@ namespace Artemis.UI.Screens.ProfileEditor { StopOnFocusLoss.AutoSave = true; ShowDataModelValues.AutoSave = true; + ShowFullPaths.AutoSave = true; FocusSelectedLayer.AutoSave = true; AlwaysApplyDataBindings.AutoSave = true; @@ -205,6 +207,7 @@ namespace Artemis.UI.Screens.ProfileEditor { StopOnFocusLoss.AutoSave = false; ShowDataModelValues.AutoSave = false; + ShowFullPaths.AutoSave = false; FocusSelectedLayer.AutoSave = false; AlwaysApplyDataBindings.AutoSave = false; diff --git a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditView.xaml b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditView.xaml index 6e3c4939e..d56908000 100644 --- a/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditView.xaml +++ b/src/Artemis.UI/Screens/Sidebar/Dialogs/ProfileEdit/ProfileEditView.xaml @@ -256,7 +256,7 @@ - + Activation conditions