From 51a21b7a8ade66426fbfa06e28eae2e8633bbf24 Mon Sep 17 00:00:00 2001 From: Robert Date: Wed, 12 Feb 2020 21:18:00 +0100 Subject: [PATCH] UI VM factories - Shortened names for readibility Layer properties - Ensure only LayerBrushes can add properties and make sure that method instantiates a keyframe engine Layer properties UI - Respond to properties being added/removed --- src/Artemis.Core/Models/Profile/Layer.cs | 4 +- .../LayerProperties/BaseLayerProperty.cs | 133 +++++++++++------- .../Profile/LayerProperties/LayerProperty.cs | 60 ++------ .../Plugins/LayerBrush/LayerBrush.cs | 19 ++- .../Services/Interfaces/ILayerService.cs | 10 +- src/Artemis.Core/Services/LayerService.cs | 12 +- .../ColorBrush.cs | 2 +- src/Artemis.UI/Artemis.UI.csproj | 3 +- .../Events/ProfileElementEventArgs.cs | 22 +++ .../{IViewModelFactory.cs => IVMFactory.cs} | 24 ++-- src/Artemis.UI/Ninject/UiModule.cs | 2 +- .../Screens/Module/ModuleRootViewModel.cs | 8 +- .../LayerPropertiesViewModel.cs | 115 +++++++++++---- .../LayerProperties/LayerPropertyViewModel.cs | 16 +-- .../PropertyTreeChildViewModel.cs | 8 ++ .../PropertyTree/PropertyTreeItemViewModel.cs | 13 ++ .../PropertyTreeParentViewModel.cs | 70 +++++---- .../PropertyTree/PropertyTreeViewModel.cs | 37 ++--- .../Timeline/PropertyTimelineViewModel.cs | 36 +++-- .../Timeline/PropertyTrackViewModel.cs | 10 +- .../ProfileTree/ProfileTreeViewModel.cs | 10 +- .../ProfileTree/TreeItem/FolderViewModel.cs | 12 +- .../ProfileTree/TreeItem/LayerViewModel.cs | 6 +- .../ProfileTree/TreeItem/TreeItemViewModel.cs | 16 +-- .../Visualization/ProfileViewModel.cs | 8 +- .../Screens/Settings/SettingsViewModel.cs | 8 +- .../Screens/Sidebar/SidebarViewModel.cs | 8 +- .../Interfaces/IProfileEditorService.cs | 9 +- .../Services/ProfileEditorService.cs | 39 ++--- 29 files changed, 417 insertions(+), 303 deletions(-) create mode 100644 src/Artemis.UI/Events/ProfileElementEventArgs.cs rename src/Artemis.UI/Ninject/Factories/{IViewModelFactory.cs => IVMFactory.cs} (68%) diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index 9306fe3ec..0f30bcfa0 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -428,7 +428,7 @@ namespace Artemis.Core.Models.Profile /// The type of value of the layer property /// The property to apply to the layer /// True if an existing value was found and applied, otherwise false. - public bool RegisterLayerProperty(LayerProperty layerProperty) + internal bool RegisterLayerProperty(LayerProperty layerProperty) { return RegisterLayerProperty((BaseLayerProperty) layerProperty); } @@ -439,7 +439,7 @@ namespace Artemis.Core.Models.Profile /// /// The property to apply to the layer /// True if an existing value was found and applied, otherwise false. - public bool RegisterLayerProperty(BaseLayerProperty layerProperty) + internal bool RegisterLayerProperty(BaseLayerProperty layerProperty) { if (_properties.ContainsKey((layerProperty.PluginInfo.Guid, layerProperty.Id))) throw new ArtemisCoreException($"Duplicate property ID detected. Layer already contains a property with ID {layerProperty.Id}."); diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs index 1dabc6f97..a8d577407 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/BaseLayerProperty.cs @@ -28,7 +28,7 @@ namespace Artemis.Core.Models.Profile.LayerProperties // This can only be null if accessed internally if (PluginInfo == null) PluginInfo = Constants.CorePluginInfo; - + Children = new List(); BaseKeyframes = new List(); @@ -108,9 +108,9 @@ namespace Artemis.Core.Models.Profile.LayerProperties public IReadOnlyCollection UntypedKeyframes => BaseKeyframes.AsReadOnly(); /// - /// Gets or sets the keyframe engine instance of this property + /// Gets the keyframe engine instance of this property /// - public KeyframeEngine KeyframeEngine { get; set; } + public KeyframeEngine KeyframeEngine { get; internal set; } protected List BaseKeyframes { get; set; } @@ -129,50 +129,6 @@ namespace Artemis.Core.Models.Profile.LayerProperties } } - internal void ApplyToEntity() - { - var propertyEntity = Layer.LayerEntity.PropertyEntities.FirstOrDefault(p => p.Id == Id); - if (propertyEntity == null) - { - propertyEntity = new PropertyEntity {Id = Id}; - Layer.LayerEntity.PropertyEntities.Add(propertyEntity); - } - - propertyEntity.ValueType = Type.Name; - propertyEntity.Value = JsonConvert.SerializeObject(BaseValue); - propertyEntity.IsUsingKeyframes = IsUsingKeyframes; - - propertyEntity.KeyframeEntities.Clear(); - foreach (var baseKeyframe in BaseKeyframes) - { - propertyEntity.KeyframeEntities.Add(new KeyframeEntity - { - Position = baseKeyframe.Position, - Value = JsonConvert.SerializeObject(baseKeyframe.BaseValue), - EasingFunction = (int) baseKeyframe.EasingFunction - }); - } - } - - internal void ApplyToProperty(PropertyEntity propertyEntity) - { - BaseValue = DeserializePropertyValue(propertyEntity.Value); - IsUsingKeyframes = propertyEntity.IsUsingKeyframes; - - BaseKeyframes.Clear(); - foreach (var keyframeEntity in propertyEntity.KeyframeEntities.OrderBy(e => e.Position)) - { - // Create a strongly typed keyframe or else it cannot be cast later on - var keyframeType = typeof(Keyframe<>); - var keyframe = (BaseKeyframe) Activator.CreateInstance(keyframeType.MakeGenericType(Type), Layer, this); - keyframe.Position = keyframeEntity.Position; - keyframe.BaseValue = DeserializePropertyValue(keyframeEntity.Value); - keyframe.EasingFunction = (Easings.Functions) keyframeEntity.EasingFunction; - - BaseKeyframes.Add(keyframe); - } - } - /// /// Creates a new keyframe for this base property without knowing the type /// @@ -261,9 +217,29 @@ namespace Artemis.Core.Models.Profile.LayerProperties SortKeyframes(); } - internal void SortKeyframes() + /// + /// Returns the flattened index of this property on the layer + /// + /// + public int GetFlattenedIndex() { - BaseKeyframes = BaseKeyframes.OrderBy(k => k.Position).ToList(); + if (Parent == null) + return Layer.Properties.IndexOf(this); + + // Create a flattened list of all properties in their order as defined by the parent/child hierarchy + var properties = new List(); + // Iterate root properties (those with children) + foreach (var baseLayerProperty in Layer.Properties) + { + // First add self, then add all children + if (baseLayerProperty.Children.Any()) + { + properties.Add(baseLayerProperty); + properties.AddRange(baseLayerProperty.GetAllChildren()); + } + } + + return properties.IndexOf(this); } public override string ToString() @@ -271,6 +247,65 @@ namespace Artemis.Core.Models.Profile.LayerProperties return $"{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(Description)}: {Description}"; } + internal void ApplyToEntity() + { + var propertyEntity = Layer.LayerEntity.PropertyEntities.FirstOrDefault(p => p.Id == Id); + if (propertyEntity == null) + { + propertyEntity = new PropertyEntity {Id = Id}; + Layer.LayerEntity.PropertyEntities.Add(propertyEntity); + } + + propertyEntity.ValueType = Type.Name; + propertyEntity.Value = JsonConvert.SerializeObject(BaseValue); + propertyEntity.IsUsingKeyframes = IsUsingKeyframes; + + propertyEntity.KeyframeEntities.Clear(); + foreach (var baseKeyframe in BaseKeyframes) + { + propertyEntity.KeyframeEntities.Add(new KeyframeEntity + { + Position = baseKeyframe.Position, + Value = JsonConvert.SerializeObject(baseKeyframe.BaseValue), + EasingFunction = (int) baseKeyframe.EasingFunction + }); + } + } + + internal void ApplyToProperty(PropertyEntity propertyEntity) + { + BaseValue = DeserializePropertyValue(propertyEntity.Value); + IsUsingKeyframes = propertyEntity.IsUsingKeyframes; + + BaseKeyframes.Clear(); + foreach (var keyframeEntity in propertyEntity.KeyframeEntities.OrderBy(e => e.Position)) + { + // Create a strongly typed keyframe or else it cannot be cast later on + var keyframeType = typeof(Keyframe<>); + var keyframe = (BaseKeyframe) Activator.CreateInstance(keyframeType.MakeGenericType(Type), Layer, this); + keyframe.Position = keyframeEntity.Position; + keyframe.BaseValue = DeserializePropertyValue(keyframeEntity.Value); + keyframe.EasingFunction = (Easings.Functions) keyframeEntity.EasingFunction; + + BaseKeyframes.Add(keyframe); + } + } + + internal void SortKeyframes() + { + BaseKeyframes = BaseKeyframes.OrderBy(k => k.Position).ToList(); + } + + internal IEnumerable GetAllChildren() + { + var children = new List(); + children.AddRange(Children); + foreach (var layerPropertyViewModel in Children) + children.AddRange(layerPropertyViewModel.GetAllChildren()); + + return children; + } + private object DeserializePropertyValue(string value) { if (value == "null") diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index 9745b53ad..644957862 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -1,71 +1,31 @@ -using System; -using System.Collections.ObjectModel; +using System.Collections.ObjectModel; using System.Linq; +using Artemis.Core.Plugins.LayerBrush; using Artemis.Core.Plugins.Models; namespace Artemis.Core.Models.Profile.LayerProperties { /// /// Represents a property on the layer. This property is visible in the profile editor and can be key-framed (unless - /// opted out) + /// opted out). + /// To create and register a new LayerProperty use /// /// public class LayerProperty : BaseLayerProperty { - internal LayerProperty(Layer layer, BaseLayerProperty parent, string id, string name, string description) : base(layer, null, parent, id, name, description, typeof(T)) + internal LayerProperty(Layer layer, BaseLayerProperty parent, string id, string name, string description) + : base(layer, null, parent, id, name, description, typeof(T)) { } - internal LayerProperty(Layer layer, string id, string name, string description) : base(layer, null, null, id, name, description, typeof(T)) + internal LayerProperty(Layer layer, string id, string name, string description) + : base(layer, null, null, id, name, description, typeof(T)) { } - /// - /// Represents a property on the layer. This property is visible in the profile editor and can be key-framed (unless - /// opted out) - /// - /// Note: The value and keyframes of the property are stored using the ID, after adding the property to the layer - /// these are restored. - /// - /// - /// The layer the property is applied to - /// The plugin to create this property for - /// The parent of this property, use this to create a tree-hierarchy in the editor - /// A and ID identifying your property, must be unique within your plugin - /// A name for your property, this is visible in the editor - /// A description for your property, this is visible in the editor - public LayerProperty(Layer layer, PluginInfo pluginInfo, BaseLayerProperty parent, string id, string name, string description) : base(layer, pluginInfo, parent, id, name, description, - typeof(T)) + internal LayerProperty(Layer layer, PluginInfo pluginInfo, BaseLayerProperty parent, string id, string name, string description) + : base(layer, pluginInfo, parent, id, name, description, typeof(T)) { - if (layer == null) - throw new ArgumentNullException(nameof(layer)); - if (pluginInfo == null) - throw new ArgumentNullException(nameof(pluginInfo)); - if (id == null) - throw new ArgumentNullException(nameof(id)); - } - - /// - /// Represents a property on the layer. This property is visible in the profile editor and can be key-framed (unless - /// opted out) - /// - /// Note: The value and keyframes of the property are stored using the ID, after adding the property to the layer - /// these are restored. - /// - /// - /// The layer the property is applied to - /// The plugin to create this property for - /// A and ID identifying your property, must be unique within your plugin - /// A name for your property, this is visible in the editor - /// A description for your property, this is visible in the editor - public LayerProperty(Layer layer, PluginInfo pluginInfo, string id, string name, string description) : base(layer, pluginInfo, null, id, name, description, typeof(T)) - { - if (layer == null) - throw new ArgumentNullException(nameof(layer)); - if (pluginInfo == null) - throw new ArgumentNullException(nameof(pluginInfo)); - if (id == null) - throw new ArgumentNullException(nameof(id)); } /// diff --git a/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs b/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs index cf1d32cf5..1685f5022 100644 --- a/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs +++ b/src/Artemis.Core/Plugins/LayerBrush/LayerBrush.cs @@ -1,12 +1,16 @@ using System; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile.LayerProperties; +using Artemis.Core.Services; +using Artemis.Core.Services.Interfaces; using SkiaSharp; namespace Artemis.Core.Plugins.LayerBrush { public abstract class LayerBrush : IDisposable { + private ILayerService _layerService; + protected LayerBrush(Layer layer, LayerBrushDescriptor descriptor) { Layer = layer; @@ -54,6 +58,8 @@ namespace Artemis.Core.Plugins.LayerBrush { var property = new LayerProperty(Layer, Descriptor.LayerBrushProvider.PluginInfo, parent, id, name, description); Layer.RegisterLayerProperty(property); + // It's fine if this is null, it'll be picked up by SetLayerService later + _layerService?.InstantiateKeyframeEngine(property); return property; } @@ -68,9 +74,20 @@ namespace Artemis.Core.Plugins.LayerBrush /// The layer property protected LayerProperty RegisterLayerProperty(string id, string name, string description) { - var property = new LayerProperty(Layer, Descriptor.LayerBrushProvider.PluginInfo, Layer.BrushReferenceProperty.Parent, id, name, description); + var property = new LayerProperty( + Layer, Descriptor.LayerBrushProvider.PluginInfo, Layer.BrushReferenceProperty.Parent, id, name, description + ); Layer.RegisterLayerProperty(property); + // It's fine if this is null, it'll be picked up by SetLayerService later + _layerService?.InstantiateKeyframeEngine(property); return property; } + + internal void SetLayerService(ILayerService layerService) + { + _layerService = layerService; + foreach (var baseLayerProperty in Layer.Properties) + _layerService.InstantiateKeyframeEngine(baseLayerProperty); + } } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/Interfaces/ILayerService.cs b/src/Artemis.Core/Services/Interfaces/ILayerService.cs index a6f1d3682..95b098f1e 100644 --- a/src/Artemis.Core/Services/Interfaces/ILayerService.cs +++ b/src/Artemis.Core/Services/Interfaces/ILayerService.cs @@ -8,15 +8,16 @@ namespace Artemis.Core.Services.Interfaces public interface ILayerService : IArtemisService { /// - /// Instantiates and adds the described by the provided - /// to the provided . + /// Instantiates and adds the described by the provided + /// to the . /// - /// The layer to add the new layer element to + /// The layer to instantiate the brush for /// LayerBrush InstantiateLayerBrush(Layer layer); /// - /// Instantiates and adds a compatible to the provided + /// Instantiates and adds a compatible to the provided . + /// If the property already has a compatible keyframe engine, nothing happens. /// /// The layer property to apply the keyframe engine to. /// The resulting keyframe engine, if a compatible engine was found. @@ -24,6 +25,7 @@ namespace Artemis.Core.Services.Interfaces /// /// Instantiates and adds a compatible to the provided . + /// If the property already has a compatible keyframe engine, nothing happens. /// /// The layer property to apply the keyframe engine to. /// The resulting keyframe engine, if a compatible engine was found. diff --git a/src/Artemis.Core/Services/LayerService.cs b/src/Artemis.Core/Services/LayerService.cs index 2771a8c0e..6bbd0aacc 100644 --- a/src/Artemis.Core/Services/LayerService.cs +++ b/src/Artemis.Core/Services/LayerService.cs @@ -46,10 +46,13 @@ namespace Artemis.Core.Services new ConstructorArgument("layer", layer), new ConstructorArgument("descriptor", descriptor) }; - var layerElement = (LayerBrush) _kernel.Get(descriptor.LayerBrushType, arguments); - layer.LayerBrush = layerElement; + var layerBrush = (LayerBrush) _kernel.Get(descriptor.LayerBrushType, arguments); + // Set the layer service after the brush was created to avoid constructor clutter, SetLayerService will play catch-up for us. + // If layer brush implementations need the LayerService they can inject it themselves, but don't require it by default + layerBrush.SetLayerService(this); + layer.LayerBrush = layerBrush; - return layerElement; + return layerBrush; } public KeyframeEngine InstantiateKeyframeEngine(LayerProperty layerProperty) @@ -59,6 +62,9 @@ namespace Artemis.Core.Services public KeyframeEngine InstantiateKeyframeEngine(BaseLayerProperty layerProperty) { + if (layerProperty.KeyframeEngine != null && layerProperty.KeyframeEngine.CompatibleTypes.Contains(layerProperty.Type)) + return layerProperty.KeyframeEngine; + // This creates an instance of each keyframe engine, which is pretty cheap since all the expensive stuff is done during // Initialize() call but it's not ideal var keyframeEngines = _kernel.Get>(); diff --git a/src/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs b/src/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs index 88a058b69..22b4eff05 100644 --- a/src/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs +++ b/src/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs @@ -17,7 +17,7 @@ namespace Artemis.Plugins.LayerBrushes.Color public ColorBrush(Layer layer, LayerBrushDescriptor descriptor) : base(layer, descriptor) { - ColorProperty = RegisterLayerProperty("Brush.Color", "Main color", "The color of the brush."); + ColorProperty = RegisterLayerProperty("Brush.Color", "Color", "The color of the brush."); GradientTypeProperty = RegisterLayerProperty("Brush.GradientType", "Gradient type", "The scale of the noise."); GradientTypeProperty.CanUseKeyframes = false; diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index cb8eb2c40..88852323e 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -155,6 +155,7 @@ + @@ -232,7 +233,7 @@ - + diff --git a/src/Artemis.UI/Events/ProfileElementEventArgs.cs b/src/Artemis.UI/Events/ProfileElementEventArgs.cs new file mode 100644 index 000000000..cb842ac10 --- /dev/null +++ b/src/Artemis.UI/Events/ProfileElementEventArgs.cs @@ -0,0 +1,22 @@ +using System; +using Artemis.Core.Models.Profile; + +namespace Artemis.UI.Events +{ + public class ProfileElementEventArgs : EventArgs + { + public ProfileElementEventArgs(ProfileElement profileElement) + { + ProfileElement = profileElement; + } + + public ProfileElementEventArgs(ProfileElement profileElement, ProfileElement previousProfileElement) + { + ProfileElement = profileElement; + PreviousProfileElement = previousProfileElement; + } + + public ProfileElement ProfileElement { get; } + public ProfileElement PreviousProfileElement { get; } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Ninject/Factories/IViewModelFactory.cs b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs similarity index 68% rename from src/Artemis.UI/Ninject/Factories/IViewModelFactory.cs rename to src/Artemis.UI/Ninject/Factories/IVMFactory.cs index 6d9169fe9..34986e68d 100644 --- a/src/Artemis.UI/Ninject/Factories/IViewModelFactory.cs +++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs @@ -13,62 +13,62 @@ using Artemis.UI.Screens.Settings.Tabs.Devices; namespace Artemis.UI.Ninject.Factories { - public interface IViewModelFactory + public interface IVmFactory { } - public interface IModuleViewModelFactory : IViewModelFactory + public interface IModuleVmFactory : IVmFactory { ModuleRootViewModel Create(Module module); } - public interface IDeviceSettingsViewModelFactory : IViewModelFactory + public interface IDeviceSettingsVmFactory : IVmFactory { DeviceSettingsViewModel Create(ArtemisDevice device); } - public interface IProfileEditorViewModelFactory : IViewModelFactory + public interface IProfileEditorVmFactory : IVmFactory { ProfileEditorViewModel Create(ProfileModule module); } - public interface IFolderViewModelFactory : IViewModelFactory + public interface IFolderVmFactory : IVmFactory { FolderViewModel Create(ProfileElement folder); FolderViewModel Create(TreeItemViewModel parent, ProfileElement folder); } - public interface ILayerViewModelFactory : IViewModelFactory + public interface ILayerVmFactory : IVmFactory { LayerViewModel Create(TreeItemViewModel parent, ProfileElement folder); } - public interface IProfileLayerViewModelFactory : IViewModelFactory + public interface IProfileLayerVmFactory : IVmFactory { ProfileLayerViewModel Create(Layer layer); } - public interface ILayerPropertyViewModelFactory : IViewModelFactory + public interface ILayerPropertyVmFactory : IVmFactory { LayerPropertyViewModel Create(BaseLayerProperty layerProperty, LayerPropertyViewModel parent); } - public interface IPropertyTreeViewModelFactory : IViewModelFactory + public interface IPropertyTreeVmFactory : IVmFactory { PropertyTreeViewModel Create(LayerPropertiesViewModel layerPropertiesViewModel); } - public interface IPropertyTimelineViewModelFactory : IViewModelFactory + public interface IPropertyTimelineVmFactory : IVmFactory { PropertyTimelineViewModel Create(LayerPropertiesViewModel layerPropertiesViewModel); } - public interface IPropertyTrackViewModelFactory : IViewModelFactory + public interface IPropertyTrackVmFactory : IVmFactory { PropertyTrackViewModel Create(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel); } - public interface IPropertyTrackKeyframeViewModelFactory : IViewModelFactory + public interface IPropertyTrackKeyframeVmFactory : IVmFactory { PropertyTrackKeyframeViewModel Create(PropertyTrackViewModel propertyTrackViewModel, BaseKeyframe keyframe); } diff --git a/src/Artemis.UI/Ninject/UiModule.cs b/src/Artemis.UI/Ninject/UiModule.cs index 5d2bbc32d..aafece9f7 100644 --- a/src/Artemis.UI/Ninject/UiModule.cs +++ b/src/Artemis.UI/Ninject/UiModule.cs @@ -45,7 +45,7 @@ namespace Artemis.UI.Ninject { x.FromThisAssembly() .SelectAllInterfaces() - .InheritedFrom() + .InheritedFrom() .BindToFactory(); }); diff --git a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs index 929d77e89..c0f230cf4 100644 --- a/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ModuleRootViewModel.cs @@ -8,14 +8,14 @@ namespace Artemis.UI.Screens.Module { public class ModuleRootViewModel : Conductor.Collection.OneActive { - private readonly IProfileEditorViewModelFactory _profileEditorViewModelFactory; + private readonly IProfileEditorVmFactory _profileEditorVmFactory; - public ModuleRootViewModel(Core.Plugins.Abstract.Module module, IProfileEditorViewModelFactory profileEditorViewModelFactory) + public ModuleRootViewModel(Core.Plugins.Abstract.Module module, IProfileEditorVmFactory profileEditorVmFactory) { DisplayName = module?.DisplayName; Module = module; - _profileEditorViewModelFactory = profileEditorViewModelFactory; + _profileEditorVmFactory = profileEditorVmFactory; Task.Run(AddTabsAsync); } @@ -30,7 +30,7 @@ namespace Artemis.UI.Screens.Module // Create the profile editor and module VMs if (Module is ProfileModule profileModule) { - var profileEditor = _profileEditorViewModelFactory.Create(profileModule); + var profileEditor = _profileEditorVmFactory.Create(profileModule); Items.Add(profileEditor); } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs index 39e5e5f3f..bac045916 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs @@ -1,10 +1,12 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Input; using System.Windows.Media; using Artemis.Core.Events; using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Services; using Artemis.Core.Services.Interfaces; using Artemis.UI.Ninject.Factories; @@ -18,30 +20,32 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties public class LayerPropertiesViewModel : ProfileEditorPanelViewModel { private readonly ICoreService _coreService; - private readonly ILayerPropertyViewModelFactory _layerPropertyViewModelFactory; + private readonly ILayerPropertyVmFactory _layerPropertyVmFactory; private readonly IProfileEditorService _profileEditorService; private readonly ISettingsService _settingsService; + private readonly List _layerPropertyViewModels; public LayerPropertiesViewModel(IProfileEditorService profileEditorService, ICoreService coreService, ISettingsService settingsService, - ILayerPropertyViewModelFactory layerPropertyViewModelFactory, - IPropertyTreeViewModelFactory propertyTreeViewModelFactory, - IPropertyTimelineViewModelFactory propertyTimelineViewModelFactory) + ILayerPropertyVmFactory layerPropertyVmFactory, + IPropertyTreeVmFactory propertyTreeVmFactory, + IPropertyTimelineVmFactory propertyTimelineVmFactory) { _profileEditorService = profileEditorService; _coreService = coreService; _settingsService = settingsService; - _layerPropertyViewModelFactory = layerPropertyViewModelFactory; + _layerPropertyVmFactory = layerPropertyVmFactory; PixelsPerSecond = 31; - PropertyTree = propertyTreeViewModelFactory.Create(this); - PropertyTimeline = propertyTimelineViewModelFactory.Create(this); + PropertyTree = propertyTreeVmFactory.Create(this); + PropertyTimeline = propertyTimelineVmFactory.Create(this); - PopulateProperties(); + PopulateProperties(_profileEditorService.SelectedProfileElement, null); - _profileEditorService.SelectedProfileElementChanged += (sender, args) => PopulateProperties(); - _profileEditorService.SelectedProfileChanged += (sender, args) => PopulateProperties(); + _layerPropertyViewModels = new List(); + _profileEditorService.SelectedProfileElementChanged += (sender, args) => PopulateProperties(args.ProfileElement, args.PreviousProfileElement); + _profileEditorService.SelectedProfileChanged += (sender, args) => PopulateProperties(_profileEditorService.SelectedProfileElement, null); _profileEditorService.CurrentTimeChanged += ProfileEditorServiceOnCurrentTimeChanged; } @@ -68,26 +72,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties public PropertyTreeViewModel PropertyTree { get; set; } public PropertyTimelineViewModel PropertyTimeline { get; set; } - private void PopulateProperties() - { - if (_profileEditorService.SelectedProfileElement is Layer selectedLayer) - { - // Only create VMs for top-level parents, let parents populate their own children recursively - var propertyViewModels = selectedLayer.Properties - .Where(p => p.Children.Any()) - .Select(p => _layerPropertyViewModelFactory.Create(p, null)) - .ToList(); - - PropertyTree.PopulateProperties(propertyViewModels); - PropertyTimeline.PopulateProperties(propertyViewModels); - } - else - { - PropertyTree.ClearProperties(); - PropertyTimeline.ClearProperties(); - } - } - private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e) { NotifyOfPropertyChange(() => FormattedCurrentTime); @@ -100,6 +84,77 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties base.OnDeactivate(); } + #region View model managament + + private void PopulateProperties(ProfileElement profileElement, ProfileElement previousProfileElement) + { + if (previousProfileElement is Layer previousLayer) + { + previousLayer.LayerPropertyRegistered -= LayerOnPropertyRegistered; + previousLayer.LayerPropertyRemoved -= LayerOnPropertyRemoved; + } + if (profileElement is Layer layer) + { + // Create VMs for missing properties + foreach (var baseLayerProperty in layer.Properties) + { + if (_layerPropertyViewModels.All(vm => vm.LayerProperty != baseLayerProperty)) + CreatePropertyViewModel(baseLayerProperty); + } + + // Remove VMs for extra properties + foreach (var layerPropertyViewModel in _layerPropertyViewModels.ToList()) + { + if (layer.Properties.All(p => p != layerPropertyViewModel.LayerProperty)) + RemovePropertyViewModel(layerPropertyViewModel); + } + + layer.LayerPropertyRegistered += LayerOnPropertyRegistered; + layer.LayerPropertyRemoved += LayerOnPropertyRemoved; + } + } + + private void LayerOnPropertyRegistered(object sender, LayerPropertyEventArgs e) + { + Console.WriteLine("LayerOnPropertyRegistered"); + PopulateProperties(e.LayerProperty.Layer, e.LayerProperty.Layer); + } + + private void LayerOnPropertyRemoved(object sender, LayerPropertyEventArgs e) + { + Console.WriteLine("LayerOnPropertyRemoved"); + PopulateProperties(e.LayerProperty.Layer, e.LayerProperty.Layer); + } + + private LayerPropertyViewModel CreatePropertyViewModel(BaseLayerProperty layerProperty) + { + LayerPropertyViewModel parent = null; + // If the property has a parent, find it's VM + if (layerProperty.Parent != null) + { + parent = _layerPropertyViewModels.FirstOrDefault(vm => vm.LayerProperty == layerProperty.Parent); + // If no VM is found, create it + if (parent == null) + parent = CreatePropertyViewModel(layerProperty.Parent); + } + + var createdViewModel = _layerPropertyVmFactory.Create(layerProperty, parent); + _layerPropertyViewModels.Add(createdViewModel); + PropertyTree.AddLayerProperty(createdViewModel); + PropertyTimeline.AddLayerProperty(createdViewModel); + + return createdViewModel; + } + + private void RemovePropertyViewModel(LayerPropertyViewModel layerPropertyViewModel) + { + PropertyTree.RemoveLayerProperty(layerPropertyViewModel); + PropertyTimeline.RemoveLayerProperty(layerPropertyViewModel); + _layerPropertyViewModels.Remove(layerPropertyViewModel); + } + + #endregion + #region Controls public void PlayFromStart() diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs index eef1fbe50..d582a3486 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs @@ -16,8 +16,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties private readonly IProfileEditorService _profileEditorService; private bool _keyframesEnabled; - public LayerPropertyViewModel(BaseLayerProperty layerProperty, LayerPropertyViewModel parent, ILayerPropertyViewModelFactory layerPropertyViewModelFactory, IKernel kernel, - IProfileEditorService profileEditorService) + public LayerPropertyViewModel(BaseLayerProperty layerProperty, LayerPropertyViewModel parent, IKernel kernel, IProfileEditorService profileEditorService) { _kernel = kernel; _profileEditorService = profileEditorService; @@ -28,8 +27,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties Children = new List(); IsExpanded = layerProperty.ExpandByDefault; - foreach (var child in layerProperty.Children) - Children.Add(layerPropertyViewModelFactory.Create(child, this)); + Parent?.Children.Add(this); } public BaseLayerProperty LayerProperty { get; } @@ -78,15 +76,5 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties match.Initialize(this); return match; } - - public IEnumerable GetAllChildren() - { - var children = new List(); - children.AddRange(Children); - foreach (var layerPropertyViewModel in children) - children.AddRange(layerPropertyViewModel.GetAllChildren()); - - return children; - } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildViewModel.cs index b14b98ce5..9ba57552c 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeChildViewModel.cs @@ -22,5 +22,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree PropertyInputViewModel?.Update(); } } + + public override void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel) + { + } + + public override void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel) + { + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeItemViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeItemViewModel.cs index f82cc0018..79a1f7dfe 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeItemViewModel.cs @@ -16,5 +16,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree /// /// Force update regardless of visibility and keyframes public abstract void Update(bool forceUpdate); + + /// + /// Removes the layer property recursively + /// + /// + public abstract void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel); + + /// + /// Adds the layer property recursively + /// + /// + public abstract void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel); + } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeParentViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeParentViewModel.cs index 3c1e7df49..15e3059e0 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeParentViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeParentViewModel.cs @@ -9,43 +9,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree public PropertyTreeParentViewModel(LayerPropertyViewModel layerPropertyViewModel) : base(layerPropertyViewModel) { Children = new BindableCollection(); - - foreach (var childProperty in layerPropertyViewModel.Children) - { - if (childProperty.Children.Any()) - Children.Add(new PropertyTreeParentViewModel(childProperty)); - else - Children.Add(new PropertyTreeChildViewModel(childProperty)); - } - - LayerPropertyViewModel.LayerProperty.Layer.LayerPropertyRegistered += LayerOnLayerPropertyRegistered; - LayerPropertyViewModel.LayerProperty.Layer.LayerPropertyRemoved += LayerOnLayerPropertyRemoved; - } - - private void LayerOnLayerPropertyRegistered(object sender, LayerPropertyEventArgs e) - { - if (e.LayerProperty.Parent == LayerPropertyViewModel.LayerProperty) - { - // Problem is we don't have a LayerPropertyViewModel here.. - } - } - - private void LayerOnLayerPropertyRemoved(object sender, LayerPropertyEventArgs e) - { - // Remove self - if (e.LayerProperty == LayerPropertyViewModel.LayerProperty) - { - LayerPropertyViewModel.LayerProperty.Layer.LayerPropertyRemoved -= LayerOnLayerPropertyRegistered; - LayerPropertyViewModel.LayerProperty.Layer.LayerPropertyRemoved -= LayerOnLayerPropertyRemoved; - } - - // Remove child - if (e.LayerProperty.Parent == LayerPropertyViewModel.LayerProperty) - { - var child = Children.FirstOrDefault(c => c.LayerPropertyViewModel.LayerProperty == e.LayerProperty); - if (child != null) - Children.Remove(child); - } } public BindableCollection Children { get; set; } @@ -55,5 +18,38 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree foreach (var child in Children) child.Update(forceUpdate); } + + public override void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel) + { + if (layerPropertyViewModel.Parent == LayerPropertyViewModel) + { + lock (Children) + { + var index = layerPropertyViewModel.LayerProperty.Parent.Children.IndexOf(layerPropertyViewModel.LayerProperty); + if (index > Children.Count) + index = Children.Count; + if (layerPropertyViewModel.Children.Any()) + Children.Insert(index, new PropertyTreeParentViewModel(layerPropertyViewModel)); + else + Children.Insert(index, new PropertyTreeChildViewModel(layerPropertyViewModel)); + } + } + else + { + foreach (var propertyTreeItemViewModel in Children) + propertyTreeItemViewModel.AddLayerProperty(layerPropertyViewModel); + } + } + + public override void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel) + { + foreach (var child in Children.ToList()) + { + if (child.LayerPropertyViewModel == layerPropertyViewModel) + Children.Remove(child); + else + child.RemoveLayerProperty(layerPropertyViewModel); + } + } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeViewModel.cs index b0dc9f66f..36c31e7d8 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/PropertyTree/PropertyTreeViewModel.cs @@ -1,9 +1,7 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; -using Artemis.Core.Models.Profile.LayerProperties; using Artemis.UI.Services.Interfaces; using Stylet; @@ -27,26 +25,31 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree public LayerPropertiesViewModel LayerPropertiesViewModel { get; } public BindableCollection PropertyTreeItemViewModels { get; set; } - public void PopulateProperties(List properties) + public void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel) { - PropertyTreeItemViewModels.Clear(); - - // Only put parents on the top-level, let parents populate their own children recursively - foreach (var property in properties) + // Add as a root VM + if (layerPropertyViewModel.Parent == null) + PropertyTreeItemViewModels.Add(new PropertyTreeParentViewModel(layerPropertyViewModel)); + // Add recursively to one of the child VMs + else { - if (property.Children.Any()) - PropertyTreeItemViewModels.Add(new PropertyTreeParentViewModel(property)); + foreach (var propertyTreeItemViewModel in PropertyTreeItemViewModels) + propertyTreeItemViewModel.AddLayerProperty(layerPropertyViewModel); } } - public void ClearProperties() + public void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel) { - PropertyTreeItemViewModels.Clear(); - } - - public void AddLayerProperty(BaseLayerProperty layerProperty) - { - + // Remove a root VM + var rootVm = PropertyTreeItemViewModels.FirstOrDefault(vm => vm.LayerPropertyViewModel == layerPropertyViewModel); + if (rootVm != null) + PropertyTreeItemViewModels.Remove(rootVm); + // Remove recursively from one of the child VMs + else + { + foreach (var propertyTreeItemViewModel in PropertyTreeItemViewModels) + propertyTreeItemViewModel.RemoveLayerProperty(layerPropertyViewModel); + } } /// diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs index 8ba70e788..0904f2774 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTimelineViewModel.cs @@ -11,14 +11,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline public class PropertyTimelineViewModel : PropertyChangedBase { private readonly IProfileEditorService _profileEditorService; - private readonly IPropertyTrackViewModelFactory _propertyTrackViewModelFactory; + private readonly IPropertyTrackVmFactory _propertyTrackVmFactory; public PropertyTimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IProfileEditorService profileEditorService, - IPropertyTrackViewModelFactory propertyTrackViewModelFactory) + IPropertyTrackVmFactory propertyTrackVmFactory) { _profileEditorService = profileEditorService; - _propertyTrackViewModelFactory = propertyTrackViewModelFactory; + _propertyTrackVmFactory = propertyTrackVmFactory; LayerPropertiesViewModel = layerPropertiesViewModel; PropertyTrackViewModels = new BindableCollection(); @@ -54,23 +54,29 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline UpdateEndTime(); } + public void AddLayerProperty(LayerPropertyViewModel layerPropertyViewModel) + { + // Determine the index by flattening all the layer's properties + var index = layerPropertyViewModel.LayerProperty.GetFlattenedIndex(); + if (index > PropertyTrackViewModels.Count) + index = PropertyTrackViewModels.Count; + PropertyTrackViewModels.Insert(index, _propertyTrackVmFactory.Create(this, layerPropertyViewModel)); + } + + public void RemoveLayerProperty(LayerPropertyViewModel layerPropertyViewModel) + { + var vm = PropertyTrackViewModels.FirstOrDefault(v => v.LayerPropertyViewModel == layerPropertyViewModel); + if (vm != null) + PropertyTrackViewModels.Remove(vm); + } + private void CreateViewModels(LayerPropertyViewModel property) { - PropertyTrackViewModels.Add(_propertyTrackViewModelFactory.Create(this, property)); + PropertyTrackViewModels.Add(_propertyTrackVmFactory.Create(this, property)); foreach (var child in property.Children) CreateViewModels(child); } - - public void AddLayerProperty(BaseLayerProperty layerProperty) - { - throw new NotImplementedException(); - } - - public void ClearProperties() - { - PropertyTrackViewModels.Clear(); - } - + public void UpdateKeyframePositions() { foreach (var viewModel in PropertyTrackViewModels) diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackViewModel.cs index 3c7bc1480..e4f01a1c1 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/PropertyTrackViewModel.cs @@ -7,13 +7,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline { public class PropertyTrackViewModel : Screen { - private readonly IPropertyTrackKeyframeViewModelFactory _propertyTrackKeyframeViewModelFactory; + private readonly IPropertyTrackKeyframeVmFactory _propertyTrackKeyframeVmFactory; - public PropertyTrackViewModel(PropertyTimelineViewModel propertyTimelineViewModel, - LayerPropertyViewModel layerPropertyViewModel, - IPropertyTrackKeyframeViewModelFactory propertyTrackKeyframeViewModelFactory) + public PropertyTrackViewModel(PropertyTimelineViewModel propertyTimelineViewModel, LayerPropertyViewModel layerPropertyViewModel, IPropertyTrackKeyframeVmFactory propertyTrackKeyframeVmFactory) { - _propertyTrackKeyframeViewModelFactory = propertyTrackKeyframeViewModelFactory; + _propertyTrackKeyframeVmFactory = propertyTrackKeyframeVmFactory; PropertyTimelineViewModel = propertyTimelineViewModel; LayerPropertyViewModel = layerPropertyViewModel; KeyframeViewModels = new BindableCollection(); @@ -41,7 +39,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline { if (KeyframeViewModels.Any(k => k.Keyframe == keyframe)) continue; - KeyframeViewModels.Add(_propertyTrackKeyframeViewModelFactory.Create(this, keyframe)); + KeyframeViewModels.Add(_propertyTrackKeyframeVmFactory.Create(this, keyframe)); } UpdateKeyframes(PropertyTimelineViewModel.LayerPropertiesViewModel.PixelsPerSecond); diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs index 08a045114..e6ee1c533 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs @@ -11,18 +11,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree { public class ProfileTreeViewModel : ProfileEditorPanelViewModel, IDropTarget { - private readonly IFolderViewModelFactory _folderViewModelFactory; + private readonly IFolderVmFactory _folderVmFactory; private readonly IProfileEditorService _profileEditorService; private TreeItemViewModel _selectedTreeItem; private bool _updatingTree; public ProfileTreeViewModel(IProfileEditorService profileEditorService, - IFolderViewModelFactory folderViewModelFactory, - ILayerViewModelFactory layerViewModelFactory) + IFolderVmFactory folderVmFactory, + ILayerVmFactory layerVmFactory) { _profileEditorService = profileEditorService; - _folderViewModelFactory = folderViewModelFactory; + _folderVmFactory = folderVmFactory; CreateRootFolderViewModel(); _profileEditorService.SelectedProfileChanged += OnSelectedProfileChanged; @@ -105,7 +105,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree return; } - RootFolder = _folderViewModelFactory.Create(folder); + RootFolder = _folderVmFactory.Create(folder); _updatingTree = false; } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs index 1b09bd69a..63778c3b9 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/FolderViewModel.cs @@ -12,9 +12,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem IProfileEditorService profileEditorService, IDialogService dialogService, ILayerService layerService, - IFolderViewModelFactory folderViewModelFactory, - ILayerViewModelFactory layerViewModelFactory) : - base(null, folder, profileEditorService, dialogService, layerService, folderViewModelFactory, layerViewModelFactory) + IFolderVmFactory folderVmFactory, + ILayerVmFactory layerVmFactory) : + base(null, folder, profileEditorService, dialogService, layerService, folderVmFactory, layerVmFactory) { } @@ -23,9 +23,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem IProfileEditorService profileEditorService, IDialogService dialogService, ILayerService layerService, - IFolderViewModelFactory folderViewModelFactory, - ILayerViewModelFactory layerViewModelFactory) : - base(parent, folder, profileEditorService, dialogService, layerService, folderViewModelFactory, layerViewModelFactory) + IFolderVmFactory folderVmFactory, + ILayerVmFactory layerVmFactory) : + base(parent, folder, profileEditorService, dialogService, layerService, folderVmFactory, layerVmFactory) { } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs index d132dff0f..346ce07db 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/LayerViewModel.cs @@ -12,9 +12,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem IProfileEditorService profileEditorService, IDialogService dialogService, ILayerService layerService, - IFolderViewModelFactory folderViewModelFactory, - ILayerViewModelFactory layerViewModelFactory) : - base(parent, folder, profileEditorService, dialogService, layerService, folderViewModelFactory, layerViewModelFactory) + IFolderVmFactory folderVmFactory, + ILayerVmFactory layerVmFactory) : + base(parent, folder, profileEditorService, dialogService, layerService, folderVmFactory, layerVmFactory) { } diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs index a241e65ad..cbc52223d 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs @@ -14,9 +14,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem public abstract class TreeItemViewModel : PropertyChangedBase { private readonly IDialogService _dialogService; - private readonly IFolderViewModelFactory _folderViewModelFactory; + private readonly IFolderVmFactory _folderVmFactory; private readonly ILayerService _layerService; - private readonly ILayerViewModelFactory _layerViewModelFactory; + private readonly ILayerVmFactory _layerVmFactory; private readonly IProfileEditorService _profileEditorService; protected TreeItemViewModel(TreeItemViewModel parent, @@ -24,14 +24,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem IProfileEditorService profileEditorService, IDialogService dialogService, ILayerService layerService, - IFolderViewModelFactory folderViewModelFactory, - ILayerViewModelFactory layerViewModelFactory) + IFolderVmFactory folderVmFactory, + ILayerVmFactory layerVmFactory) { _profileEditorService = profileEditorService; _dialogService = dialogService; _layerService = layerService; - _folderViewModelFactory = folderViewModelFactory; - _layerViewModelFactory = layerViewModelFactory; + _folderVmFactory = folderVmFactory; + _layerVmFactory = layerVmFactory; Parent = parent; ProfileElement = profileElement; @@ -182,13 +182,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem { existing = Children.FirstOrDefault(p => p is FolderViewModel vm && vm.ProfileElement == folder); if (existing == null) - Children.Add(_folderViewModelFactory.Create((FolderViewModel) this, folder)); + Children.Add(_folderVmFactory.Create((FolderViewModel) this, folder)); } else if (profileElement is Layer layer) { existing = Children.FirstOrDefault(p => p is LayerViewModel vm && vm.ProfileElement == layer); if (existing == null) - Children.Add(_layerViewModelFactory.Create((FolderViewModel) this, layer)); + Children.Add(_layerVmFactory.Create((FolderViewModel) this, layer)); } existing?.UpdateProfileElements(); diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs index e6034ee62..0db04a2de 100644 --- a/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/Module/ProfileEditor/Visualization/ProfileViewModel.cs @@ -24,7 +24,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization { private readonly ILayerEditorService _layerEditorService; private readonly IProfileEditorService _profileEditorService; - private readonly IProfileLayerViewModelFactory _profileLayerViewModelFactory; + private readonly IProfileLayerVmFactory _profileLayerVmFactory; private readonly ISettingsService _settingsService; private readonly ISurfaceService _surfaceService; private int _activeToolIndex; @@ -37,13 +37,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization ISurfaceService surfaceService, ISettingsService settingsService, IEventAggregator eventAggregator, - IProfileLayerViewModelFactory profileLayerViewModelFactory) + IProfileLayerVmFactory profileLayerVmFactory) { _profileEditorService = profileEditorService; _layerEditorService = layerEditorService; _surfaceService = surfaceService; _settingsService = settingsService; - _profileLayerViewModelFactory = profileLayerViewModelFactory; + _profileLayerVmFactory = profileLayerVmFactory; Execute.OnUIThreadSync(() => { @@ -144,7 +144,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization foreach (var layer in layers) { if (layerViewModels.All(vm => vm.Layer != layer)) - CanvasViewModels.Add(_profileLayerViewModelFactory.Create(layer)); + CanvasViewModels.Add(_profileLayerVmFactory.Create(layer)); } // Remove layers that no longer exist diff --git a/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs index e5171808b..179272f33 100644 --- a/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/SettingsViewModel.cs @@ -20,7 +20,7 @@ namespace Artemis.UI.Screens.Settings { public class SettingsViewModel : MainScreenViewModel { - private readonly IDeviceSettingsViewModelFactory _deviceSettingsViewModelFactory; + private readonly IDeviceSettingsVmFactory _deviceSettingsVmFactory; private readonly IKernel _kernel; private readonly IPluginService _pluginService; private readonly ISettingsService _settingsService; @@ -32,7 +32,7 @@ namespace Artemis.UI.Screens.Settings IPluginService pluginService, IWindowManager windowManager, ISettingsService settingsService, - IDeviceSettingsViewModelFactory deviceSettingsViewModelFactory) + IDeviceSettingsVmFactory deviceSettingsVmFactory) { DisplayName = "Settings"; DisplayIcon = PackIconKind.Settings; @@ -43,7 +43,7 @@ namespace Artemis.UI.Screens.Settings _pluginService = pluginService; _windowManager = windowManager; _settingsService = settingsService; - _deviceSettingsViewModelFactory = deviceSettingsViewModelFactory; + _deviceSettingsVmFactory = deviceSettingsVmFactory; DeviceSettingsViewModels = new BindableCollection(); Plugins = new BindableCollection(); @@ -112,7 +112,7 @@ namespace Artemis.UI.Screens.Settings { DeviceSettingsViewModels.Clear(); foreach (var device in _surfaceService.ActiveSurface.Devices) - DeviceSettingsViewModels.Add(_deviceSettingsViewModelFactory.Create(device)); + DeviceSettingsViewModels.Add(_deviceSettingsVmFactory.Create(device)); // TODO: GetPluginsOfType isn't ideal here as it doesn't include disabled plugins Plugins.Clear(); diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs index 13eee3dc0..fee3b7e50 100644 --- a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs @@ -13,12 +13,12 @@ namespace Artemis.UI.Screens.Sidebar { public class SidebarViewModel : PropertyChangedBase { - private readonly IModuleViewModelFactory _moduleViewModelFactory; + private readonly IModuleVmFactory _moduleVmFactory; private readonly IPluginService _pluginService; - public SidebarViewModel(List defaultSidebarItems, IModuleViewModelFactory moduleViewModelFactory, IPluginService pluginService) + public SidebarViewModel(List defaultSidebarItems, IModuleVmFactory moduleVmFactory, IPluginService pluginService) { - _moduleViewModelFactory = moduleViewModelFactory; + _moduleVmFactory = moduleVmFactory; _pluginService = pluginService; DefaultSidebarItems = defaultSidebarItems; @@ -76,7 +76,7 @@ namespace Artemis.UI.Screens.Sidebar SelectedItem = screen; // Modules have a VM that must be created, use a factory and set the result as the selected item else if (sidebarItemObject is Core.Plugins.Abstract.Module module) - SelectedItem = _moduleViewModelFactory.Create(module); + SelectedItem = _moduleVmFactory.Create(module); } public void AddModule(Core.Plugins.Abstract.Module module) diff --git a/src/Artemis.UI/Services/Interfaces/IProfileEditorService.cs b/src/Artemis.UI/Services/Interfaces/IProfileEditorService.cs index 2a7fb99b0..01d389a45 100644 --- a/src/Artemis.UI/Services/Interfaces/IProfileEditorService.cs +++ b/src/Artemis.UI/Services/Interfaces/IProfileEditorService.cs @@ -1,6 +1,7 @@ using System; using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Abstract; +using Artemis.UI.Events; namespace Artemis.UI.Services.Interfaces { @@ -21,22 +22,22 @@ namespace Artemis.UI.Services.Interfaces /// /// Occurs when a new profile is selected /// - event EventHandler SelectedProfileChanged; + event EventHandler SelectedProfileChanged; /// /// Occurs then the currently selected profile is updated /// - event EventHandler SelectedProfileUpdated; + event EventHandler SelectedProfileUpdated; /// /// Occurs when a new profile element is selected /// - event EventHandler SelectedProfileElementChanged; + event EventHandler SelectedProfileElementChanged; /// /// Occurs when the currently selected profile element is updated /// - event EventHandler SelectedProfileElementUpdated; + event EventHandler SelectedProfileElementUpdated; /// /// Occurs when the current editor time is changed diff --git a/src/Artemis.UI/Services/ProfileEditorService.cs b/src/Artemis.UI/Services/ProfileEditorService.cs index e8cbfe5af..bc976c79b 100644 --- a/src/Artemis.UI/Services/ProfileEditorService.cs +++ b/src/Artemis.UI/Services/ProfileEditorService.cs @@ -4,6 +4,7 @@ using Artemis.Core.Models.Profile; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; +using Artemis.UI.Events; using Artemis.UI.Services.Interfaces; namespace Artemis.UI.Services @@ -39,29 +40,31 @@ namespace Artemis.UI.Services public void ChangeSelectedProfile(Profile profile) { + var profileElementEvent = new ProfileElementEventArgs(profile, SelectedProfile); SelectedProfile = profile; UpdateProfilePreview(); - OnSelectedProfileChanged(); + OnSelectedProfileChanged(profileElementEvent); } public void UpdateSelectedProfile() { _profileService.UpdateProfile(SelectedProfile, false); UpdateProfilePreview(); - OnSelectedProfileElementUpdated(); + OnSelectedProfileElementUpdated(new ProfileElementEventArgs(SelectedProfile)); } public void ChangeSelectedProfileElement(ProfileElement profileElement) { + var profileElementEvent = new ProfileElementEventArgs(profileElement, SelectedProfileElement); SelectedProfileElement = profileElement; - OnSelectedProfileElementChanged(); + OnSelectedProfileElementChanged(profileElementEvent); } public void UpdateSelectedProfileElement() { _profileService.UpdateProfile(SelectedProfile, true); UpdateProfilePreview(); - OnSelectedProfileElementUpdated(); + OnSelectedProfileElementUpdated(new ProfileElementEventArgs(SelectedProfileElement)); } @@ -91,7 +94,7 @@ namespace Artemis.UI.Services public void UndoUpdateProfile(ProfileModule module) { _profileService.UndoUpdateProfile(SelectedProfile, module); - OnSelectedProfileChanged(); + OnSelectedProfileChanged(new ProfileElementEventArgs(SelectedProfile, SelectedProfile)); if (SelectedProfileElement != null) { @@ -107,7 +110,7 @@ namespace Artemis.UI.Services public void RedoUpdateProfile(ProfileModule module) { _profileService.RedoUpdateProfile(SelectedProfile, module); - OnSelectedProfileChanged(); + OnSelectedProfileChanged(new ProfileElementEventArgs(SelectedProfile, SelectedProfile)); if (SelectedProfileElement != null) { @@ -120,10 +123,10 @@ namespace Artemis.UI.Services UpdateProfilePreview(); } - public event EventHandler SelectedProfileChanged; - public event EventHandler SelectedProfileUpdated; - public event EventHandler SelectedProfileElementChanged; - public event EventHandler SelectedProfileElementUpdated; + public event EventHandler SelectedProfileChanged; + public event EventHandler SelectedProfileUpdated; + public event EventHandler SelectedProfileElementChanged; + public event EventHandler SelectedProfileElementUpdated; public event EventHandler CurrentTimeChanged; public event EventHandler ProfilePreviewUpdated; @@ -137,24 +140,24 @@ namespace Artemis.UI.Services _coreService.ModuleUpdatingDisabled = false; } - protected virtual void OnSelectedProfileElementUpdated() + protected virtual void OnSelectedProfileChanged(ProfileElementEventArgs e) { - SelectedProfileElementUpdated?.Invoke(this, EventArgs.Empty); + SelectedProfileChanged?.Invoke(this, e); } - protected virtual void OnSelectedProfileElementChanged() + protected virtual void OnSelectedProfileUpdated(ProfileElementEventArgs e) { - SelectedProfileElementChanged?.Invoke(this, EventArgs.Empty); + SelectedProfileUpdated?.Invoke(this, e); } - protected virtual void OnSelectedProfileUpdated() + protected virtual void OnSelectedProfileElementChanged(ProfileElementEventArgs e) { - SelectedProfileUpdated?.Invoke(this, EventArgs.Empty); + SelectedProfileElementChanged?.Invoke(this, e); } - protected virtual void OnSelectedProfileChanged() + protected virtual void OnSelectedProfileElementUpdated(ProfileElementEventArgs e) { - SelectedProfileChanged?.Invoke(this, EventArgs.Empty); + SelectedProfileElementUpdated?.Invoke(this, e); } protected virtual void OnCurrentTimeChanged()