From 21beffc0a9b2dbf1b257f130f382aa943ab06b1e Mon Sep 17 00:00:00 2001 From: Robert Date: Thu, 3 Sep 2020 20:16:01 +0200 Subject: [PATCH] Data bindings - WIP commit Layer/effect config dialogs - Don't require specific ctor parameter names --- .../Profile/DataBindings/DataBinding.cs | 84 +++++++++++++-- .../DataBindings/DataBindingModifier.cs | 52 +++++++-- src/Artemis.Core/Models/Profile/Layer.cs | 2 + .../LayerProperties/BaseLayerProperty.cs | 32 +++++- .../Profile/LayerProperties/LayerProperty.cs | 7 ++ .../Profile/DataBindings/DataBindingEntity.cs | 2 + .../Entities/Profile/PropertyEntity.cs | 3 +- .../DataBindings/DataBindingModifierView.xaml | 96 +++++++++++++++++ .../DataBindingModifierView.xaml.cs | 26 +++++ .../DataBindingModifierViewModel.cs | 15 +++ .../DataBindings/DataBindingView.xaml | 101 ++---------------- .../DataBindings/DataBindingViewModel.cs | 68 ++++++++++-- .../DataBindings/DataBindingsViewModel.cs | 9 +- .../Tree/TreePropertyGroupViewModel.cs | 32 ++++-- .../Tabs/Plugins/PluginSettingsViewModel.cs | 9 +- 15 files changed, 408 insertions(+), 130 deletions(-) create mode 100644 src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml create mode 100644 src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml.cs create mode 100644 src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierViewModel.cs diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs index 3bb2066b4..10a2c206f 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBinding.cs @@ -15,18 +15,23 @@ namespace Artemis.Core public class DataBinding { private readonly List _modifiers = new List(); + private bool _isInitialized; - public DataBinding(BaseLayerProperty layerProperty, PropertyInfo targetProperty) + internal DataBinding(BaseLayerProperty layerProperty, PropertyInfo targetProperty) { LayerProperty = layerProperty; TargetProperty = targetProperty; + Entity = new DataBindingEntity(); + + ApplyToEntity(); } - public DataBinding(BaseLayerProperty layerProperty, PropertyInfo targetProperty, DataBindingEntity entity) + internal DataBinding(BaseLayerProperty layerProperty, DataBindingEntity entity) { LayerProperty = layerProperty; - TargetProperty = targetProperty; Entity = entity; + + ApplyToDataBinding(); } /// @@ -37,7 +42,7 @@ namespace Artemis.Core /// /// Gets the inner property this data binding targets /// - public PropertyInfo TargetProperty { get; } + public PropertyInfo TargetProperty { get; private set; } /// /// Gets the currently used instance of the data model that contains the source of the data binding @@ -49,13 +54,25 @@ namespace Artemis.Core /// public string SourcePropertyPath { get; private set; } + public DataBindingMode Mode { get; set; } + + /// + /// Gets or sets the easing time of the data binding + /// + public TimeSpan EasingTime { get; set; } + + /// + /// Gets ors ets the easing function of the data binding + /// + public Easings.Functions EasingFunction { get; set; } + /// /// Gets a list of modifiers applied to this data binding /// public IReadOnlyList Modifiers => _modifiers.AsReadOnly(); /// - /// Gets the compiled function that gets the current value of the data binding target + /// Gets the compiled function that gets the current value of the data binding target /// public Func CompiledTargetAccessor { get; private set; } @@ -131,15 +148,60 @@ namespace Artemis.Core return dataBindingValue; } - internal void Initialize(IDataModelService dataModelService, IDataBindingService dataBindingService) + internal void ApplyToEntity() { - // Source + // General + Entity.TargetProperty = TargetProperty?.Name; + Entity.DataBindingMode = (int) Mode; + Entity.EasingTime = EasingTime; + Entity.EasingFunction = (int) EasingFunction; + + // Data model + Entity.SourceDataModelGuid = SourceDataModel?.PluginInfo?.Guid; + Entity.SourcePropertyPath = SourcePropertyPath; // Modifiers + Entity.Modifiers.Clear(); + foreach (var dataBindingModifier in Modifiers) + { + dataBindingModifier.ApplyToEntity(); + Entity.Modifiers.Add(dataBindingModifier.Entity); + } + } + internal void ApplyToDataBinding() + { + // General + TargetProperty = LayerProperty.GetDataBindingProperties()?.FirstOrDefault(p => p.Name == Entity.TargetProperty); + Mode = (DataBindingMode) Entity.DataBindingMode; + EasingTime = Entity.EasingTime; + EasingFunction = (Easings.Functions) Entity.EasingFunction; - foreach (var dataBindingModifier in Modifiers) + // Data model is done during Initialize + + // Modifiers + foreach (var dataBindingModifierEntity in Entity.Modifiers) + _modifiers.Add(new DataBindingModifier(this, dataBindingModifierEntity)); + } + + internal void Initialize(IDataModelService dataModelService, IDataBindingService dataBindingService) + { + if (_isInitialized) + throw new ArtemisCoreException("Data binding is already initialized"); + + // Source + if (Entity.SourceDataModelGuid != null) + { + var dataModel = dataModelService.GetPluginDataModelByGuid(Entity.SourceDataModelGuid.Value); + if (dataModel != null && dataModel.ContainsPath(Entity.SourcePropertyPath)) + UpdateSource(dataModel, Entity.SourcePropertyPath); + } + + // Modifiers + foreach (var dataBindingModifier in Modifiers) dataBindingModifier.Initialize(dataModelService, dataBindingService); + + _isInitialized = true; } private void CreateExpression() @@ -158,4 +220,10 @@ namespace Artemis.Core CompiledTargetAccessor = lambda.Compile(); } } + + public enum DataBindingMode + { + Override, + Add + } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs index 4603bd9a6..6710cf8e9 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingModifier.cs @@ -4,6 +4,7 @@ using System.Linq.Expressions; using Artemis.Core.DataModelExpansions; using Artemis.Core.Services; using Artemis.Storage.Entities.Profile.DataBindings; +using Microsoft.VisualBasic; using Newtonsoft.Json; namespace Artemis.Core @@ -14,26 +15,26 @@ namespace Artemis.Core public class DataBindingModifier { private DataBinding _dataBinding; + private bool _isInitialized; /// - /// Creates a new instance of the class + /// Creates a new instance of the class /// - public DataBindingModifier(DataBinding dataBinding, ProfileRightSideType parameterType) + /// The type of the parameter, can either be dynamic (based on a data model value) or static + public DataBindingModifier(ProfileRightSideType parameterType) { - DataBinding = dataBinding; ParameterType = parameterType; Entity = new DataBindingModifierEntity(); + + ApplyToEntity(); } - /// - /// Creates a new instance of the class - /// - public DataBindingModifier(DataBinding dataBinding, DataBindingModifierEntity entity) + internal DataBindingModifier(DataBinding dataBinding, DataBindingModifierEntity entity) { DataBinding = dataBinding; - ParameterType = (ProfileRightSideType) entity.ParameterType; - Order = entity.Order; Entity = entity; + + ApplyToDataBindingModifier(); } /// @@ -192,6 +193,9 @@ namespace Artemis.Core internal void Initialize(IDataModelService dataModelService, IDataBindingService dataBindingService) { + if (_isInitialized) + throw new ArtemisCoreException("Data binding modifier is already initialized"); + // Modifier type if (Entity.ModifierTypePluginGuid != null) { @@ -207,6 +211,7 @@ namespace Artemis.Core if (dataModel != null && dataModel.ContainsPath(Entity.ParameterPropertyPath)) UpdateParameter(dataModel, Entity.ParameterPropertyPath); } + // Static parameter else if (ParameterType == ProfileRightSideType.Static && Entity.ParameterStaticValue != null) { // Use the target type so JSON.NET has a better idea what to do @@ -227,7 +232,7 @@ namespace Artemis.Core UpdateParameter(staticValue); } - // Static parameter + _isInitialized = true; } @@ -291,5 +296,32 @@ namespace Artemis.Core Expression.Property ); } + + internal void ApplyToEntity() + { + // Modifier + Entity.ModifierType = ModifierType?.GetType().Name; + Entity.ModifierTypePluginGuid = ModifierType?.PluginInfo.Guid; + + // General + Entity.Order = Order; + Entity.ParameterType = (int) ParameterType; + + // Parameter + Entity.ParameterDataModelGuid = ParameterDataModel?.PluginInfo.Guid; + Entity.ParameterPropertyPath = ParameterPropertyPath; + Entity.ParameterStaticValue = JsonConvert.SerializeObject(ParameterStaticValue); + } + + internal void ApplyToDataBindingModifier() + { + // Modifier type is done during Initialize + + // General + Order = Entity.Order; + ParameterType = (ProfileRightSideType) Entity.ParameterType; + + // Parameter is done during initialize + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 7ced36400..a1f3595e6 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -112,6 +112,7 @@ namespace Artemis.Core internal set => SetAndNotify(ref _layerBrush, value); } + /// public override string ToString() { return $"[Layer] {nameof(Name)}: {Name}, {nameof(Order)}: {Order}"; @@ -138,6 +139,7 @@ namespace Artemis.Core return keyframes; } + /// protected override void Dispose(bool disposing) { if (!disposing) diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs index f807ea4a6..5d3836415 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs @@ -10,7 +10,7 @@ namespace Artemis.Core /// public abstract class BaseLayerProperty { - private readonly List _dataBindings = new List(); + protected readonly List _dataBindings = new List(); private bool _isHidden; private bool _keyframesEnabled; @@ -31,15 +31,15 @@ namespace Artemis.Core /// /// Gets whether keyframes are supported on this type of property /// - public bool KeyframesSupported { get; protected internal set; } = true; - + public bool KeyframesSupported { get; protected internal set; } = true; + /// /// Gets whether data bindings are supported on this type of property /// public bool DataBindingsSupported { get; protected internal set; } = true; /// - /// Gets a read-only collection of the currently applied data bindings + /// Gets a read-only collection of the currently applied data bindings /// public IReadOnlyCollection DataBindings => _dataBindings.AsReadOnly(); @@ -141,6 +141,30 @@ namespace Artemis.Core ApplyDataBinding(dataBinding); } + /// + /// Adds a new data binding targeting the given property to the collection + /// + /// The property the new data binding should target + /// The newly created data binding + public DataBinding AddDataBinding(PropertyInfo targetProperty) + { + var dataBinding = new DataBinding(this, targetProperty); + _dataBindings.Add(dataBinding); + + return dataBinding; + } + + /// + /// Removes the provided data binding from the collection + /// + /// The data binding to remove + public void RemoveDataBinding(DataBinding dataBinding) + { + _dataBindings.Remove(dataBinding); + } + + + #endregion #region Events diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index 7ecaaf718..8680a6214 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -255,6 +255,13 @@ namespace Artemis.Core (Easings.Functions) k.EasingFunction, this ))); + + _dataBindings.Clear(); + foreach (var entityDataBindingEntity in entity.DataBindingEntities) + { + var dataBinding = new DataBinding(this, entityDataBindingEntity); + _dataBindings.Add(dataBinding); + } } catch (JsonException e) { diff --git a/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingEntity.cs b/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingEntity.cs index da9d85c7c..761acbeee 100644 --- a/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/DataBindings/DataBindingEntity.cs @@ -10,6 +10,7 @@ namespace Artemis.Storage.Entities.Profile.DataBindings Modifiers = new List(); } + public string TargetProperty { get; set; } public Guid? SourceDataModelGuid { get; set; } public string SourcePropertyPath { get; set; } public int DataBindingMode { get; set; } @@ -17,5 +18,6 @@ namespace Artemis.Storage.Entities.Profile.DataBindings public int EasingFunction { get; set; } public List Modifiers { get; set; } + } } \ No newline at end of file diff --git a/src/Artemis.Storage/Entities/Profile/PropertyEntity.cs b/src/Artemis.Storage/Entities/Profile/PropertyEntity.cs index d2c82aef7..c26baa1ce 100644 --- a/src/Artemis.Storage/Entities/Profile/PropertyEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/PropertyEntity.cs @@ -9,6 +9,7 @@ namespace Artemis.Storage.Entities.Profile public PropertyEntity() { KeyframeEntities = new List(); + DataBindingEntities = new List(); } public Guid PluginGuid { get; set; } @@ -18,6 +19,6 @@ namespace Artemis.Storage.Entities.Profile public bool KeyframesEnabled { get; set; } public List KeyframeEntities { get; set; } - public DataBindingEntity DataBindingEntity { get; set; } + public List DataBindingEntities { get; set; } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml new file mode 100644 index 000000000..b9bb6eb77 --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml.cs new file mode 100644 index 000000000..ab48662ff --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierView.xaml.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings +{ + /// + /// Interaction logic for DataBindingModifierView.xaml + /// + public partial class DataBindingModifierView : UserControl + { + public DataBindingModifierView() + { + InitializeComponent(); + } + } +} diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierViewModel.cs new file mode 100644 index 000000000..e0c0c9e37 --- /dev/null +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingModifierViewModel.cs @@ -0,0 +1,15 @@ +using Artemis.Core; +using Stylet; + +namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings +{ + public class DataBindingModifierViewModel : PropertyChangedBase + { + public DataBindingModifierViewModel(DataBindingModifier modifier) + { + Modifier = modifier; + } + + public DataBindingModifier Modifier { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml index 731957d47..856fe4b5d 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingView.xaml @@ -8,8 +8,10 @@ xmlns:utilities="clr-namespace:Artemis.UI.Utilities" xmlns:dd="urn:gong-wpf-dragdrop" xmlns:s="https://github.com/canton7/Stylet" + xmlns:local="clr-namespace:Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings" mc:Ignorable="d" - d:DesignHeight="450" d:DesignWidth="800"> + d:DesignHeight="450" d:DesignWidth="800" + d:DataContext="{d:DesignInstance local:DataBindingViewModel}"> @@ -165,103 +167,20 @@ - - - - - - - - - - - - - - - - - - - + + + + + + diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs index d4954dbc9..678e04626 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingViewModel.cs @@ -1,4 +1,5 @@ -using System.Reflection; +using System.Linq; +using System.Reflection; using Artemis.Core; using Stylet; @@ -6,15 +7,70 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings { public class DataBindingViewModel : PropertyChangedBase { - public DataBindingViewModel(BaseLayerProperty layerProperty, PropertyInfo dataBindingProperty) + private DataBinding _dataBinding; + + public DataBindingViewModel(BaseLayerProperty layerProperty, PropertyInfo targetProperty) { - DisplayName = dataBindingProperty.Name.ToUpper(); LayerProperty = layerProperty; - DataBindingProperty = dataBindingProperty; + TargetProperty = targetProperty; + + DisplayName = TargetProperty.Name.ToUpper(); + ModifierViewModels = new BindableCollection(); + DataBinding = layerProperty.DataBindings.FirstOrDefault(d => d.TargetProperty == targetProperty); } - public string DisplayName { get; } public BaseLayerProperty LayerProperty { get; } - public PropertyInfo DataBindingProperty { get; } + public PropertyInfo TargetProperty { get; } + public string DisplayName { get; } + public BindableCollection ModifierViewModels { get; } + + public DataBinding DataBinding + { + get => _dataBinding; + set + { + if (!SetAndNotify(ref _dataBinding, value)) return; + UpdateModifierViewModels(); + } + } + + public void EnableDataBinding() + { + if (DataBinding != null) + return; + + DataBinding = LayerProperty.AddDataBinding(TargetProperty); + } + + public void RemoveDataBinding() + { + if (DataBinding == null) + return; + + var toRemove = DataBinding; + DataBinding = null; + LayerProperty.RemoveDataBinding(toRemove); + } + + public void AddModifier() + { + if (DataBinding == null) + return; + + var modifier = new DataBindingModifier(ProfileRightSideType.Dynamic); + DataBinding.AddModifier(modifier); + + ModifierViewModels.Add(new DataBindingModifierViewModel(modifier)); + } + + private void UpdateModifierViewModels() + { + ModifierViewModels.Clear(); + if (DataBinding == null) + return; + + foreach (var dataBindingModifier in DataBinding.Modifiers) + ModifierViewModels.Add(new DataBindingModifierViewModel(dataBindingModifier)); + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs index 915ff91b6..1e9a9df24 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs @@ -31,16 +31,21 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings private void Initialise() { + DataBindingViewModel = null; + DataBindingsTabsViewModel = null; + var properties = LayerProperty.GetDataBindingProperties(); - if (properties.Count == 0) + if (properties == null || properties.Count == 0) return; + // Create a data binding VM for each data bindable property. These VMs will be responsible for retrieving + // and creating the actual data bindings if (properties.Count == 1) DataBindingViewModel = new DataBindingViewModel(LayerProperty, properties.First()); else { DataBindingsTabsViewModel = new DataBindingsTabsViewModel(); - foreach (var dataBindingProperty in LayerProperty.GetDataBindingProperties()) + foreach (var dataBindingProperty in properties) DataBindingsTabsViewModel.Tabs.Add(new DataBindingViewModel(LayerProperty, dataBindingProperty)); } } diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs index ac7bbce96..acd2f68bf 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyGroupViewModel.cs @@ -1,8 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Reflection; using Artemis.Core.LayerBrushes; using Artemis.Core.LayerEffects; using Artemis.Core.Services; +using Artemis.UI.Exceptions; using Artemis.UI.Screens.ProfileEditor.Dialogs; using Artemis.UI.Screens.ProfileEditor.LayerProperties.Abstract; using Artemis.UI.Shared.Services; @@ -39,33 +42,48 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree public void OpenBrushSettings() { - var configurationViewModel = LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush.ConfigurationDialog; + var layerBrush = LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush; + var configurationViewModel = layerBrush.ConfigurationDialog; if (configurationViewModel == null) return; try { - var layerBrush = new ConstructorArgument("layerBrush", LayerPropertyGroupViewModel.LayerPropertyGroup.LayerBrush); - var viewModel = (BrushConfigurationViewModel) _kernel.Get(configurationViewModel.Type, layerBrush); + // Limit to one constructor, there's no need to have more and it complicates things anyway + var constructors = configurationViewModel.Type.GetConstructors(); + if (constructors.Length != 1) + throw new ArtemisUIException("Brush configuration dialogs must have exactly one constructor"); + + // Find the BaseLayerBrush parameter, it is required by the base constructor so its there for sure + var brushParameter = constructors.First().GetParameters().First(p => typeof(BaseLayerBrush).IsAssignableFrom(p.ParameterType)); + var argument = new ConstructorArgument(brushParameter.Name, layerBrush); + var viewModel = (BrushConfigurationViewModel) _kernel.Get(configurationViewModel.Type, argument); + _windowManager.ShowDialog(new LayerBrushSettingsWindowViewModel(viewModel)); } catch (Exception e) { _dialogService.ShowExceptionDialog("An exception occured while trying to show the brush's settings window", e); - throw; } } public void OpenEffectSettings() { - var configurationViewModel = LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect.ConfigurationDialog; + var layerEffect = LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect; + var configurationViewModel = layerEffect.ConfigurationDialog; if (configurationViewModel == null) return; try { - var layerEffect = new ConstructorArgument("layerEffect", LayerPropertyGroupViewModel.LayerPropertyGroup.LayerEffect); - var viewModel = (EffectConfigurationViewModel) _kernel.Get(configurationViewModel.Type, layerEffect); + // Limit to one constructor, there's no need to have more and it complicates things anyway + var constructors = configurationViewModel.Type.GetConstructors(); + if (constructors.Length != 1) + throw new ArtemisUIException("Effect configuration dialogs must have exactly one constructor"); + + var effectParameter = constructors.First().GetParameters().First(p => typeof(BaseLayerEffect).IsAssignableFrom(p.ParameterType)); + var argument = new ConstructorArgument(effectParameter.Name, layerEffect); + var viewModel = (EffectConfigurationViewModel) _kernel.Get(configurationViewModel.Type, argument); _windowManager.ShowDialog(new LayerEffectSettingsWindowViewModel(viewModel)); } catch (Exception e) diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs index 3aae21c6f..ab58491c8 100644 --- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs @@ -10,6 +10,7 @@ using Artemis.Core.LayerBrushes; using Artemis.Core.LayerEffects; using Artemis.Core.Modules; using Artemis.Core.Services; +using Artemis.UI.Exceptions; using Artemis.UI.Shared.Services; using MaterialDesignThemes.Wpf; using Ninject; @@ -88,7 +89,13 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins try { - var plugin = new ConstructorArgument("plugin", Plugin); + // Limit to one constructor, there's no need to have more and it complicates things anyway + var constructors = configurationViewModel.Type.GetConstructors(); + if (constructors.Length != 1) + throw new ArtemisUIException("Plugin configuration dialogs must have exactly one constructor"); + + var pluginParameter = constructors.First().GetParameters().First(p => typeof(Plugin).IsAssignableFrom(p.ParameterType)); + var plugin = new ConstructorArgument(pluginParameter.Name, Plugin); var viewModel = (PluginConfigurationViewModel) _kernel.Get(configurationViewModel.Type, plugin); _windowManager.ShowDialog(new PluginSettingsWindowViewModel(viewModel, Icon)); }