diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index abb71c632..7cec76f9a 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -288,13 +288,10 @@ namespace Artemis.Core if (LayerBrush?.BaseProperties?.PropertiesInitialized == false || LayerBrush?.BrushType != LayerBrushType.Regular) return; - lock (Timeline) - { - RenderTimeline(Timeline, canvas); - foreach (Timeline extraTimeline in Timeline.ExtraTimelines) - RenderTimeline(extraTimeline, canvas); - Timeline.ClearDelta(); - } + RenderTimeline(Timeline, canvas); + foreach (Timeline extraTimeline in Timeline.ExtraTimelines.ToList()) + RenderTimeline(extraTimeline, canvas); + Timeline.ClearDelta(); } private void ApplyTimeline(Timeline timeline) @@ -384,6 +381,7 @@ namespace Artemis.Core { // ignored } + Renderer.Close(); } } diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs index c586fd548..02a8f1f40 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs @@ -26,7 +26,12 @@ namespace Artemis.Core /// /// Gets the unique path of the property on the layer /// - public string Path { get; } + string Path { get; } + + /// + /// Gets the type of the property + /// + Type PropertyType { get; } /// /// Initializes the layer property diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs index 362b93b37..9e1123694 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -39,20 +39,15 @@ namespace Artemis.Core _keyframes = new List>(); } - /// - /// Returns the type of the property - /// - public Type GetPropertyType() - { - return typeof(T); - } - /// public PropertyDescriptionAttribute PropertyDescription { get; internal set; } /// public string Path { get; private set; } + /// + public Type PropertyType => typeof(T); + /// public void Update(Timeline timeline) { diff --git a/src/Artemis.UI.Shared/Controls/ArtemisIcon.xaml b/src/Artemis.UI.Shared/Controls/ArtemisIcon.xaml index 2809b772b..33405a778 100644 --- a/src/Artemis.UI.Shared/Controls/ArtemisIcon.xaml +++ b/src/Artemis.UI.Shared/Controls/ArtemisIcon.xaml @@ -15,7 +15,7 @@ - + diff --git a/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs b/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs index 3b9e10223..96c5bb5a5 100644 --- a/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs +++ b/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs @@ -13,7 +13,8 @@ namespace Artemis.UI.Shared public abstract class PropertyInputViewModel : PropertyInputViewModel { private bool _inputDragging; - [AllowNull] private T _inputValue = default!; + [AllowNull] + private T _inputValue = default!; /// /// Creates a new instance of the class @@ -24,11 +25,6 @@ namespace Artemis.UI.Shared { LayerProperty = layerProperty; ProfileEditorService = profileEditorService; - LayerProperty.Updated += LayerPropertyOnUpdated; - LayerProperty.CurrentValueSet += LayerPropertyOnUpdated; - LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange; - LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange; - UpdateInputValue(); } /// @@ -41,11 +37,6 @@ namespace Artemis.UI.Shared { LayerProperty = layerProperty; ProfileEditorService = profileEditorService; - LayerProperty.Updated += LayerPropertyOnUpdated; - LayerProperty.CurrentValueSet += LayerPropertyOnUpdated; - LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange; - LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange; - UpdateInputValue(); } /// @@ -87,20 +78,27 @@ namespace Artemis.UI.Shared internal override object InternalGuard { get; } = new(); - #region IDisposable + #region Overrides of Screen /// - protected override void Dispose(bool disposing) + protected override void OnInitialActivate() { - if (disposing) - { - LayerProperty.Updated -= LayerPropertyOnUpdated; - LayerProperty.CurrentValueSet -= LayerPropertyOnUpdated; - LayerProperty.DataBindingEnabled -= LayerPropertyOnDataBindingChange; - LayerProperty.DataBindingDisabled -= LayerPropertyOnDataBindingChange; - } + LayerProperty.Updated += LayerPropertyOnUpdated; + LayerProperty.CurrentValueSet += LayerPropertyOnUpdated; + LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange; + LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange; + UpdateInputValue(); + base.OnInitialActivate(); + } - base.Dispose(disposing); + /// + protected override void OnClose() + { + LayerProperty.Updated -= LayerPropertyOnUpdated; + LayerProperty.CurrentValueSet -= LayerPropertyOnUpdated; + LayerProperty.DataBindingEnabled -= LayerPropertyOnDataBindingChange; + LayerProperty.DataBindingDisabled -= LayerPropertyOnDataBindingChange; + base.OnClose(); } #endregion @@ -207,7 +205,7 @@ namespace Artemis.UI.Shared /// /// For internal use only, implement instead. /// - public abstract class PropertyInputViewModel : ValidatingModelBase, IDisposable + public abstract class PropertyInputViewModel : Screen { /// /// For internal use only, implement instead. @@ -228,30 +226,5 @@ namespace Artemis.UI.Shared /// // ReSharper disable once UnusedMember.Global internal abstract object InternalGuard { get; } - - #region IDisposable - - /// - /// Releases the unmanaged resources used by the object and optionally releases the managed resources. - /// - /// - /// to release both managed and unmanaged resources; - /// to release only unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - } - } - - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - #endregion } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs index 32b6a92e1..2b17579b2 100644 --- a/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs +++ b/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Windows; using Artemis.Core; using Artemis.Core.Modules; @@ -41,6 +42,11 @@ namespace Artemis.UI.Shared.Services /// ReadOnlyCollection RegisteredPropertyEditors { get; } + /// + /// Gets or sets a boolean indicating whether the editor is currently playing + /// + bool Playing { get; set; } + /// /// Changes the selected profile /// @@ -129,6 +135,12 @@ namespace Artemis.UI.Shared.Services /// TimeSpan SnapToTimeline(TimeSpan time, TimeSpan tolerance, bool snapToSegments, bool snapToCurrentTime, List? snapTimes = null); + /// + /// Determines if there is a matching registration for the provided layer property + /// + /// The layer property to try to find a view model for + bool CanCreatePropertyInputViewModel(ILayerProperty layerProperty); + /// /// If a matching registration is found, creates a new supporting /// @@ -160,7 +172,13 @@ namespace Artemis.UI.Shared.Services /// Gets a boolean indicating whether a profile element is on the clipboard /// bool GetCanPasteProfileElement(); - + + /// + /// Determines all LEDs on the current active surface contained in the specified rectangle + /// + /// A list containing all the LEDs that are in the provided rect + List GetLedsInRectangle(Rect rect); + /// /// Occurs when a new profile is selected /// diff --git a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs index 5b0b30cea..e31950e37 100644 --- a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs +++ b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Windows; using Artemis.Core; using Artemis.Core.Modules; using Artemis.Core.Services; @@ -11,6 +12,7 @@ using Newtonsoft.Json; using Ninject; using Ninject.Parameters; using Serilog; +using SkiaSharp.Views.WPF; using Stylet; namespace Artemis.UI.Shared.Services @@ -71,6 +73,8 @@ namespace Artemis.UI.Shared.Services } public ReadOnlyCollection RegisteredPropertyEditors => _registeredPropertyEditors.AsReadOnly(); + + public bool Playing { get; set; } public Profile? SelectedProfile { get; private set; } public RenderProfileElement? SelectedProfileElement { get; private set; } public ILayerProperty? SelectedDataBinding { get; private set; } @@ -302,6 +306,15 @@ namespace Artemis.UI.Shared.Services return time; } + public bool CanCreatePropertyInputViewModel(ILayerProperty layerProperty) + { + PropertyInputRegistration? registration = RegisteredPropertyEditors.FirstOrDefault(r => r.SupportedType == layerProperty.PropertyType); + if (registration == null && layerProperty.PropertyType.IsEnum) + registration = RegisteredPropertyEditors.FirstOrDefault(r => r.SupportedType == typeof(Enum)); + + return registration != null; + } + public PropertyInputViewModel? CreatePropertyInputViewModel(LayerProperty layerProperty) { Type? viewModelType = null; @@ -339,6 +352,11 @@ namespace Artemis.UI.Shared.Services return SelectedProfile?.Module; } + public List GetLedsInRectangle(Rect rect) + { + return _surfaceService.ActiveSurface.Devices.SelectMany(d => d.Leds).Where(led => led.AbsoluteRectangle.IntersectsWith(rect.ToSKRect())).ToList(); + } + #region Copy/paste public ProfileElement? DuplicateProfileElement(ProfileElement profileElement) diff --git a/src/Artemis.UI/DefaultTypes/PropertyInput/BrushPropertyInputViewModel.cs b/src/Artemis.UI/DefaultTypes/PropertyInput/BrushPropertyInputViewModel.cs index ea641ad68..d0b5e1b16 100644 --- a/src/Artemis.UI/DefaultTypes/PropertyInput/BrushPropertyInputViewModel.cs +++ b/src/Artemis.UI/DefaultTypes/PropertyInput/BrushPropertyInputViewModel.cs @@ -14,14 +14,10 @@ namespace Artemis.UI.PropertyInput private readonly IPluginManagementService _pluginManagementService; private BindableCollection _descriptors; - public BrushPropertyInputViewModel(LayerProperty layerProperty, - IProfileEditorService profileEditorService, - IPluginManagementService pluginManagementService) : base(layerProperty, profileEditorService) + public BrushPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService, IPluginManagementService pluginManagementService) + : base(layerProperty, profileEditorService) { _pluginManagementService = pluginManagementService; - - _pluginManagementService.PluginEnabled += PluginManagementServiceOnPluginManagementLoaded; - _pluginManagementService.PluginDisabled += PluginManagementServiceOnPluginManagementLoaded; UpdateEnumValues(); } @@ -60,18 +56,22 @@ namespace Artemis.UI.PropertyInput UpdateEnumValues(); } - #region IDisposable + #region Overrides of Screen /// - protected override void Dispose(bool disposing) + protected override void OnInitialActivate() { - if (disposing) - { - _pluginManagementService.PluginEnabled -= PluginManagementServiceOnPluginManagementLoaded; - _pluginManagementService.PluginDisabled -= PluginManagementServiceOnPluginManagementLoaded; - } + _pluginManagementService.PluginEnabled += PluginManagementServiceOnPluginManagementLoaded; + _pluginManagementService.PluginDisabled += PluginManagementServiceOnPluginManagementLoaded; + base.OnInitialActivate(); + } - base.Dispose(disposing); + /// + protected override void OnClose() + { + _pluginManagementService.PluginEnabled -= PluginManagementServiceOnPluginManagementLoaded; + _pluginManagementService.PluginDisabled -= PluginManagementServiceOnPluginManagementLoaded; + base.OnClose(); } #endregion diff --git a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs index b73ccea26..32daa2030 100644 --- a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs +++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs @@ -17,6 +17,7 @@ using Artemis.UI.Screens.ProfileEditor.Visualization.Tools; using Artemis.UI.Screens.Settings.Debug; using Artemis.UI.Screens.Settings.Tabs.Devices; using Artemis.UI.Screens.Settings.Tabs.Plugins; +using Artemis.UI.Screens.Shared; using Stylet; namespace Artemis.UI.Ninject.Factories @@ -53,15 +54,15 @@ namespace Artemis.UI.Ninject.Factories public interface IProfileLayerVmFactory : IVmFactory { - ProfileLayerViewModel Create(Layer layer, ProfileViewModel profileViewModel); + ProfileLayerViewModel Create(Layer layer, PanZoomViewModel panZoomViewModel); } public interface IVisualizationToolVmFactory : IVmFactory { - ViewpointMoveToolViewModel ViewpointMoveToolViewModel(ProfileViewModel profileViewModel); - EditToolViewModel EditToolViewModel(ProfileViewModel profileViewModel); - SelectionToolViewModel SelectionToolViewModel(ProfileViewModel profileViewModel); - SelectionRemoveToolViewModel SelectionRemoveToolViewModel(ProfileViewModel profileViewModel); + ViewpointMoveToolViewModel ViewpointMoveToolViewModel(PanZoomViewModel panZoomViewModel); + EditToolViewModel EditToolViewModel(PanZoomViewModel panZoomViewModel); + SelectionToolViewModel SelectionToolViewModel(PanZoomViewModel panZoomViewModel); + SelectionRemoveToolViewModel SelectionRemoveToolViewModel(PanZoomViewModel panZoomViewModel); } public interface IDataModelConditionsVmFactory : IVmFactory @@ -82,10 +83,10 @@ namespace Artemis.UI.Ninject.Factories TreeGroupViewModel TreeGroupViewModel(LayerPropertyGroupViewModel layerPropertyGroupViewModel); TimelineGroupViewModel TimelineGroupViewModel(LayerPropertyGroupViewModel layerPropertyGroupViewModel); - TreeViewModel TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection layerPropertyGroups); + TreeViewModel TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IObservableCollection layerPropertyGroups); EffectsViewModel EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel); - TimelineViewModel TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection layerPropertyGroups); - TimelineSegmentViewModel TimelineSegmentViewModel(SegmentViewModelType segment, BindableCollection layerPropertyGroups); + TimelineViewModel TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IObservableCollection layerPropertyGroups); + TimelineSegmentViewModel TimelineSegmentViewModel(SegmentViewModelType segment, IObservableCollection layerPropertyGroups); } public interface IDataBindingsVmFactory diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs index b772e27e4..23e73dcd1 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/DataBindings/DataBindingsViewModel.cs @@ -17,9 +17,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings { _profileEditorService = profileEditorService; _dataBindingsVmFactory = dataBindingsVmFactory; - - _profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged; - CreateDataBindingViewModels(); } public int SelectedItemIndex @@ -27,13 +24,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings get => _selectedItemIndex; set => SetAndNotify(ref _selectedItemIndex, value); } - - protected override void OnClose() - { - _profileEditorService.SelectedDataBindingChanged -= ProfileEditorServiceOnSelectedDataBindingChanged; - base.OnClose(); - } - + private void CreateDataBindingViewModels() { Items.Clear(); @@ -48,7 +39,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings // and creating the actual data bindings foreach (IDataBindingRegistration registration in registrations) Items.Add(_dataBindingsVmFactory.DataBindingViewModel(registration)); - + SelectedItemIndex = 0; } @@ -56,5 +47,23 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings { CreateDataBindingViewModels(); } + + #region Overrides of Screen + + /// + protected override void OnInitialActivate() + { + _profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged; + CreateDataBindingViewModels(); + base.OnInitialActivate(); + } + + protected override void OnClose() + { + _profileEditorService.SelectedDataBindingChanged -= ProfileEditorServiceOnSelectedDataBindingChanged; + base.OnClose(); + } + + #endregion } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs index 5da0d6163..527d2907c 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs @@ -23,11 +23,10 @@ using MouseButtonEventArgs = System.Windows.Input.MouseButtonEventArgs; namespace Artemis.UI.Screens.ProfileEditor.LayerProperties { - public class LayerPropertiesViewModel : Conductor.Collection.AllActive, IProfileEditorPanelViewModel, IDropTarget + public class LayerPropertiesViewModel : Conductor.Collection.AllActive, IProfileEditorPanelViewModel, IDropTarget { private readonly ILayerPropertyVmFactory _layerPropertyVmFactory; private LayerPropertyGroupViewModel _brushPropertyGroup; - private bool _playing; private bool _repeating; private bool _repeatSegment; private bool _repeatTimeline = true; @@ -49,31 +48,27 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties CoreService = coreService; SettingsService = settingsService; - LayerPropertyGroups = new BindableCollection(); PropertyChanged += HandlePropertyTreeIndexChanged; // Left side - TreeViewModel = _layerPropertyVmFactory.TreeViewModel(this, LayerPropertyGroups); + TreeViewModel = _layerPropertyVmFactory.TreeViewModel(this, Items); + TreeViewModel.ConductWith(this); EffectsViewModel = _layerPropertyVmFactory.EffectsViewModel(this); - Items.Add(TreeViewModel); - Items.Add(EffectsViewModel); + EffectsViewModel.ConductWith(this); // Right side - StartTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.Start, LayerPropertyGroups); - MainTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.Main, LayerPropertyGroups); - EndTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.End, LayerPropertyGroups); - TimelineViewModel = _layerPropertyVmFactory.TimelineViewModel(this, LayerPropertyGroups); + StartTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.Start, Items); + StartTimelineSegmentViewModel.ConductWith(this); + MainTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.Main, Items); + MainTimelineSegmentViewModel.ConductWith(this); + EndTimelineSegmentViewModel = _layerPropertyVmFactory.TimelineSegmentViewModel(SegmentViewModelType.End, Items); + EndTimelineSegmentViewModel.ConductWith(this); + TimelineViewModel = _layerPropertyVmFactory.TimelineViewModel(this, Items); + TimelineViewModel.ConductWith(this); DataBindingsViewModel = dataBindingsViewModel; - Items.Add(StartTimelineSegmentViewModel); - Items.Add(MainTimelineSegmentViewModel); - Items.Add(EndTimelineSegmentViewModel); - Items.Add(TimelineViewModel); - Items.Add(DataBindingsViewModel); + DataBindingsViewModel.ConductWith(this); } - public BindableCollection LayerPropertyGroups { get; } - - #region Child VMs public TreeViewModel TreeViewModel { get; } @@ -92,8 +87,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties public bool Playing { - get => _playing; - set => SetAndNotify(ref _playing, value); + get => ProfileEditorService.Playing; + set + { + ProfileEditorService.Playing = value; + NotifyOfPropertyChange(nameof(Playing)); + } } public bool Repeating @@ -239,8 +238,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties public List GetAllLayerPropertyGroupViewModels() { - List groups = LayerPropertyGroups.ToList(); - List toAdd = groups.SelectMany(g => g.Children).Where(g => g is LayerPropertyGroupViewModel).Cast().ToList(); + List groups = Items.ToList(); + List toAdd = groups.SelectMany(g => g.Items).Where(g => g is LayerPropertyGroupViewModel).Cast().ToList(); groups.AddRange(toAdd); return groups; } @@ -254,9 +253,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties SelectedLayer.LayerBrushUpdated -= SelectedLayerOnLayerBrushUpdated; // Clear old properties - foreach (LayerPropertyGroupViewModel layerPropertyGroupViewModel in LayerPropertyGroups) - layerPropertyGroupViewModel.Dispose(); - LayerPropertyGroups.Clear(); + Items.Clear(); _brushPropertyGroup = null; if (profileElement == null) @@ -271,8 +268,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties SelectedLayer.LayerBrushUpdated += SelectedLayerOnLayerBrushUpdated; // Add the built-in root groups of the layer - LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.General)); - LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.Transform)); + Items.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.General)); + Items.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.Transform)); } ApplyLayerBrush(); @@ -302,14 +299,14 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties if (_brushPropertyGroup != null) { - LayerPropertyGroups.Remove(_brushPropertyGroup); + Items.Remove(_brushPropertyGroup); _brushPropertyGroup = null; } if (SelectedLayer.LayerBrush != null) { _brushPropertyGroup = _layerPropertyVmFactory.LayerPropertyGroupViewModel(SelectedLayer.LayerBrush.BaseProperties); - LayerPropertyGroups.Add(_brushPropertyGroup); + Items.Add(_brushPropertyGroup); } SortProperties(); @@ -321,19 +318,19 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties return; // Remove VMs of effects no longer applied on the layer - List toRemove = LayerPropertyGroups + List toRemove = Items .Where(l => l.LayerPropertyGroup.LayerEffect != null && !SelectedProfileElement.LayerEffects.Contains(l.LayerPropertyGroup.LayerEffect)) .ToList(); - LayerPropertyGroups.RemoveRange(toRemove); + Items.RemoveRange(toRemove); foreach (LayerPropertyGroupViewModel layerPropertyGroupViewModel in toRemove) - layerPropertyGroupViewModel.Dispose(); + layerPropertyGroupViewModel.RequestClose(); foreach (BaseLayerEffect layerEffect in SelectedProfileElement.LayerEffects) { - if (LayerPropertyGroups.Any(l => l.LayerPropertyGroup.LayerEffect == layerEffect) || layerEffect.BaseProperties == null) + if (Items.Any(l => l.LayerPropertyGroup.LayerEffect == layerEffect) || layerEffect.BaseProperties == null) continue; - LayerPropertyGroups.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerEffect.BaseProperties)); + Items.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerEffect.BaseProperties)); } SortProperties(); @@ -342,11 +339,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties private void SortProperties() { // Get all non-effect properties - List nonEffectProperties = LayerPropertyGroups + List nonEffectProperties = Items .Where(l => l.TreeGroupViewModel.GroupType != LayerEffectRoot) .ToList(); // Order the effects - List effectProperties = LayerPropertyGroups + List effectProperties = Items .Where(l => l.TreeGroupViewModel.GroupType == LayerEffectRoot) .OrderBy(l => l.LayerPropertyGroup.LayerEffect.Order) .ToList(); @@ -355,14 +352,14 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties for (int index = 0; index < nonEffectProperties.Count; index++) { LayerPropertyGroupViewModel layerPropertyGroupViewModel = nonEffectProperties[index]; - LayerPropertyGroups.Move(LayerPropertyGroups.IndexOf(layerPropertyGroupViewModel), index); + ((BindableCollection) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index); } // Put the effect properties after, sorted by their order for (int index = 0; index < effectProperties.Count; index++) { LayerPropertyGroupViewModel layerPropertyGroupViewModel = effectProperties[index]; - LayerPropertyGroups.Move(LayerPropertyGroups.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count); + ((BindableCollection) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count); } } @@ -424,22 +421,22 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties private void MoveBefore(LayerPropertyGroupViewModel source, LayerPropertyGroupViewModel target) { - if (LayerPropertyGroups.IndexOf(target) == LayerPropertyGroups.IndexOf(source) + 1) + if (Items.IndexOf(target) == Items.IndexOf(source) + 1) return; - LayerPropertyGroups.Move(LayerPropertyGroups.IndexOf(source), LayerPropertyGroups.IndexOf(target)); + ((BindableCollection) Items).Move(Items.IndexOf(source), Items.IndexOf(target)); } private void MoveAfter(LayerPropertyGroupViewModel source, LayerPropertyGroupViewModel target) { - LayerPropertyGroups.Remove(source); - LayerPropertyGroups.Insert(LayerPropertyGroups.IndexOf(target) + 1, source); + Items.Remove(source); + Items.Insert(Items.IndexOf(target) + 1, source); } private void ApplyCurrentEffectsOrder() { int order = 1; - foreach (LayerPropertyGroupViewModel groupViewModel in LayerPropertyGroups.Where(p => p.TreeGroupViewModel.GroupType == LayerEffectRoot)) + foreach (LayerPropertyGroupViewModel groupViewModel in Items.Where(p => p.TreeGroupViewModel.GroupType == LayerEffectRoot)) { groupViewModel.UpdateOrder(order); order++; @@ -530,7 +527,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties private TimeSpan CalculateEndTime() { - List keyframeViewModels = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframeViewModels(false)).ToList(); + List keyframeViewModels = Items.SelectMany(g => g.GetAllKeyframeViewModels(false)).ToList(); // If there are no keyframes, don't stop at all if (!keyframeViewModels.Any()) @@ -627,7 +624,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties // If holding down shift, snap to the closest segment or keyframe if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) { - List snapTimes = LayerPropertyGroups.SelectMany(g => g.GetAllKeyframeViewModels(true)).Select(k => k.Position).ToList(); + List snapTimes = Items.SelectMany(g => g.GetAllKeyframeViewModels(true)).Select(k => k.Position).ToList(); TimeSpan snappedTime = ProfileEditorService.SnapToTimeline(newTime, TimeSpan.FromMilliseconds(1000f / ProfileEditorService.PixelsPerSecond * 5), true, false, snapTimes); ProfileEditorService.CurrentTime = snappedTime; return; diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs index 318c3eb17..3407026fe 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs @@ -5,42 +5,53 @@ using Artemis.Core; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline; using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree; +using Artemis.UI.Shared.Services; using Stylet; namespace Artemis.UI.Screens.ProfileEditor.LayerProperties { - public sealed class LayerPropertyGroupViewModel : PropertyChangedBase, IDisposable + public sealed class LayerPropertyGroupViewModel : Conductor.Collection.AllActive { + private readonly IProfileEditorService _profileEditorService; private readonly ILayerPropertyVmFactory _layerPropertyVmFactory; private bool _isVisible; + private TreeGroupViewModel _treeGroupViewModel; + private TimelineGroupViewModel _timelineGroupViewModel; - public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, ILayerPropertyVmFactory layerPropertyVmFactory) + public LayerPropertyGroupViewModel(LayerPropertyGroup layerPropertyGroup, IProfileEditorService profileEditorService, ILayerPropertyVmFactory layerPropertyVmFactory) { + _profileEditorService = profileEditorService; _layerPropertyVmFactory = layerPropertyVmFactory; LayerPropertyGroup = layerPropertyGroup; - Children = new BindableCollection(); - - TreeGroupViewModel = layerPropertyVmFactory.TreeGroupViewModel(this); - TimelineGroupViewModel = layerPropertyVmFactory.TimelineGroupViewModel(this); - - LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged; IsVisible = !LayerPropertyGroup.IsHidden; - PopulateChildren(); + TreeGroupViewModel = _layerPropertyVmFactory.TreeGroupViewModel(this); + TreeGroupViewModel.ConductWith(this); + TimelineGroupViewModel = _layerPropertyVmFactory.TimelineGroupViewModel(this); + TimelineGroupViewModel.ConductWith(this); } public LayerPropertyGroup LayerPropertyGroup { get; } - public TreeGroupViewModel TreeGroupViewModel { get; } - public TimelineGroupViewModel TimelineGroupViewModel { get; } - public BindableCollection Children { get; } + + public TreeGroupViewModel TreeGroupViewModel + { + get => _treeGroupViewModel; + set => SetAndNotify(ref _treeGroupViewModel, value); + } + + public TimelineGroupViewModel TimelineGroupViewModel + { + get => _timelineGroupViewModel; + set => SetAndNotify(ref _timelineGroupViewModel, value); + } public bool IsVisible { get => _isVisible; set => SetAndNotify(ref _isVisible, value); } - + public bool IsExpanded { get => LayerPropertyGroup.ProfileElement.IsPropertyGroupExpanded(LayerPropertyGroup); @@ -51,25 +62,26 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties } } - #region IDisposable - - /// - public void Dispose() + + protected override void OnInitialActivate() { - TimelineGroupViewModel.Dispose(); - LayerPropertyGroup.VisibilityChanged -= LayerPropertyGroupOnVisibilityChanged; - foreach (PropertyChangedBase child in Children) - { - if (child is IDisposable disposableChild) - disposableChild.Dispose(); - } + LayerPropertyGroup.VisibilityChanged += LayerPropertyGroupOnVisibilityChanged; + + PopulateChildren(); + + base.OnInitialActivate(); } - #endregion + protected override void OnClose() + { + LayerPropertyGroup.VisibilityChanged -= LayerPropertyGroupOnVisibilityChanged; + base.OnClose(); + } public void UpdateOrder(int order) { - LayerPropertyGroup.LayerEffect.Order = order; + if (LayerPropertyGroup.LayerEffect != null) + LayerPropertyGroup.LayerEffect.Order = order; NotifyOfPropertyChange(nameof(IsExpanded)); } @@ -79,7 +91,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties if (expandedOnly && !IsExpanded) return result; - foreach (PropertyChangedBase child in Children) + foreach (Screen child in Items) { if (child is LayerPropertyViewModel layerPropertyViewModel) result.AddRange(layerPropertyViewModel.TimelinePropertyViewModel.GetAllKeyframeViewModels()); @@ -98,11 +110,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties /// The position at which to start removing keyframes, if null this will end at the last keyframe public void WipeKeyframes(TimeSpan? start, TimeSpan? end) { - foreach (PropertyChangedBase child in Children) + foreach (Screen item in Items) { - if (child is LayerPropertyViewModel layerPropertyViewModel) + if (item is LayerPropertyViewModel layerPropertyViewModel) layerPropertyViewModel.TimelinePropertyViewModel.WipeKeyframes(start, end); - else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel) + else if (item is LayerPropertyGroupViewModel layerPropertyGroupViewModel) layerPropertyGroupViewModel.WipeKeyframes(start, end); } @@ -118,11 +130,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties /// The amount to shift the keyframes for public void ShiftKeyframes(TimeSpan? start, TimeSpan? end, TimeSpan amount) { - foreach (PropertyChangedBase child in Children) + foreach (Screen item in Items) { - if (child is LayerPropertyViewModel layerPropertyViewModel) + if (item is LayerPropertyViewModel layerPropertyViewModel) layerPropertyViewModel.TimelinePropertyViewModel.ShiftKeyframes(start, end, amount); - else if (child is LayerPropertyGroupViewModel layerPropertyGroupViewModel) + else if (item is LayerPropertyGroupViewModel layerPropertyGroupViewModel) layerPropertyGroupViewModel.ShiftKeyframes(start, end, amount); } @@ -147,16 +159,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties // Create VMs for properties on the group if (propertyAttribute != null && value is ILayerProperty layerProperty) { - LayerPropertyViewModel layerPropertyViewModel = _layerPropertyVmFactory.LayerPropertyViewModel(layerProperty); - // After creation ensure a supported input VM was found, if not, discard the VM - if (!layerPropertyViewModel.TreePropertyViewModel.HasPropertyInputViewModel) - layerPropertyViewModel.Dispose(); - else - Children.Add(layerPropertyViewModel); + // Ensure a supported input VM was found, otherwise don't add it + if (_profileEditorService.CanCreatePropertyInputViewModel(layerProperty)) + Items.Add(_layerPropertyVmFactory.LayerPropertyViewModel(layerProperty)); } // Create VMs for child groups on this group, resulting in a nested structure else if (groupAttribute != null && value is LayerPropertyGroup layerPropertyGroup) - Children.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerPropertyGroup)); + Items.Add(_layerPropertyVmFactory.LayerPropertyGroupViewModel(layerPropertyGroup)); } } } diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs index b72463006..3512f8b70 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs @@ -1,5 +1,4 @@ -using System; -using Artemis.Core; +using Artemis.Core; using Artemis.UI.Ninject.Factories; using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline; using Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree; @@ -7,23 +6,38 @@ using Stylet; namespace Artemis.UI.Screens.ProfileEditor.LayerProperties { - public sealed class LayerPropertyViewModel : PropertyChangedBase, IDisposable + public sealed class LayerPropertyViewModel : Screen { - private bool _isVisible; - private bool _isHighlighted; private bool _isExpanded; + private bool _isHighlighted; + private bool _isVisible; + private ITimelinePropertyViewModel _timelinePropertyViewModel; + private ITreePropertyViewModel _treePropertyViewModel; + public LayerPropertyViewModel(ILayerProperty layerProperty, IPropertyVmFactory propertyVmFactory) { LayerProperty = layerProperty; - TreePropertyViewModel = propertyVmFactory.TreePropertyViewModel(layerProperty, this); - TimelinePropertyViewModel = propertyVmFactory.TimelinePropertyViewModel(layerProperty, this); + TreePropertyViewModel = propertyVmFactory.TreePropertyViewModel(LayerProperty, this); + TreePropertyViewModel.ConductWith(this); + TimelinePropertyViewModel = propertyVmFactory.TimelinePropertyViewModel(LayerProperty, this); + TimelinePropertyViewModel.ConductWith(this); } public ILayerProperty LayerProperty { get; } - public ITreePropertyViewModel TreePropertyViewModel { get; } - public ITimelinePropertyViewModel TimelinePropertyViewModel { get; } + + public ITreePropertyViewModel TreePropertyViewModel + { + get => _treePropertyViewModel; + set => SetAndNotify(ref _treePropertyViewModel, value); + } + + public ITimelinePropertyViewModel TimelinePropertyViewModel + { + get => _timelinePropertyViewModel; + set => SetAndNotify(ref _timelinePropertyViewModel, value); + } public bool IsVisible { @@ -42,11 +56,5 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties get => _isExpanded; set => SetAndNotify(ref _isExpanded, value); } - - public void Dispose() - { - TreePropertyViewModel?.Dispose(); - TimelinePropertyViewModel?.Dispose(); - } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineGroupView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineGroupView.xaml index 3de69b24d..3c97a9b35 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineGroupView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineGroupView.xaml @@ -48,7 +48,7 @@ diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineGroupViewModel.cs index 8463787bc..c2a67a002 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineGroupViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineGroupViewModel.cs @@ -7,7 +7,7 @@ using Stylet; namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline { - public sealed class TimelineGroupViewModel : PropertyChangedBase, IDisposable + public sealed class TimelineGroupViewModel : Screen { private readonly IProfileEditorService _profileEditorService; @@ -19,13 +19,9 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline LayerPropertyGroup = LayerPropertyGroupViewModel.LayerPropertyGroup; KeyframePositions = new BindableCollection(); - _profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; - LayerPropertyGroupViewModel.PropertyChanged += LayerPropertyGroupViewModelOnPropertyChanged; - - UpdateKeyframePositions(); + UpdateKeyframePositions(); } - - + public LayerPropertyGroupViewModel LayerPropertyGroupViewModel { get; } public LayerPropertyGroup LayerPropertyGroup { get; } @@ -39,16 +35,26 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline .Select(p => p.Position.TotalSeconds * _profileEditorService.PixelsPerSecond)); } - #region IDisposable + #region Overrides of Screen - public void Dispose() + /// + protected override void OnInitialActivate() + { + _profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; + LayerPropertyGroupViewModel.PropertyChanged += LayerPropertyGroupViewModelOnPropertyChanged; + base.OnInitialActivate(); + } + + /// + protected override void OnClose() { _profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged; LayerPropertyGroupViewModel.PropertyChanged -= LayerPropertyGroupViewModelOnPropertyChanged; + base.OnClose(); } #endregion - + #region Event handlers private void LayerPropertyGroupViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e) diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs index 3bd23bd47..e6c5bd408 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs @@ -20,12 +20,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline _profileEditorService = profileEditorService; LayerPropertyKeyframe = layerPropertyKeyframe; EasingViewModels = new BindableCollection(); - - _profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; - LayerPropertyKeyframe.PropertyChanged += LayerPropertyKeyframeOnPropertyChanged; } - - + public LayerPropertyKeyframe LayerPropertyKeyframe { get; } public BindableCollection EasingViewModels { get; } @@ -50,15 +46,29 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline public TimeSpan Position => LayerPropertyKeyframe.Position; public ILayerPropertyKeyframe Keyframe => LayerPropertyKeyframe; - public void Dispose() + #region Overrides of Screen + + protected override void OnInitialActivate() + { + _profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; + LayerPropertyKeyframe.PropertyChanged += LayerPropertyKeyframeOnPropertyChanged; + + base.OnInitialActivate(); + } + + protected override void OnClose() { _profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged; LayerPropertyKeyframe.PropertyChanged -= LayerPropertyKeyframeOnPropertyChanged; foreach (TimelineEasingViewModel timelineEasingViewModel in EasingViewModels) timelineEasingViewModel.EasingModeSelected -= TimelineEasingViewModelOnEasingModeSelected; + + base.OnClose(); } + #endregion + public void Update() { X = _profileEditorService.PixelsPerSecond * LayerPropertyKeyframe.Position.TotalSeconds; @@ -159,7 +169,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline #endregion #region Context menu actions - + public void Delete(bool save = true) { LayerPropertyKeyframe.LayerProperty.RemoveKeyframe(LayerPropertyKeyframe); @@ -170,7 +180,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline #endregion } - public interface ITimelineKeyframeViewModel : IScreen, IDisposable + public interface ITimelineKeyframeViewModel : IScreen { bool IsSelected { get; set; } TimeSpan Position { get; } diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelinePropertyView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelinePropertyView.xaml index 844e39add..86a320891 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelinePropertyView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelinePropertyView.xaml @@ -10,9 +10,7 @@ d:DesignHeight="450" d:DesignWidth="800" HorizontalAlignment="Stretch"> - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs index 06d87ef35..d2b041d41 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelinePropertyViewModel.cs @@ -18,11 +18,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline LayerProperty = layerProperty; LayerPropertyViewModel = layerPropertyViewModel; - - LayerProperty.KeyframesToggled += LayerPropertyOnKeyframesToggled; - LayerProperty.KeyframeAdded += LayerPropertyOnKeyframeAdded; - LayerProperty.KeyframeRemoved += LayerPropertyOnKeyframeRemoved; - UpdateKeyframes(); } public LayerProperty LayerProperty { get; } @@ -59,15 +54,27 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline List> toShift = LayerProperty.Keyframes.Where(k => k.Position > start && k.Position < end).ToList(); foreach (LayerPropertyKeyframe keyframe in toShift) keyframe.Position += amount; - + UpdateKeyframes(); } - - public void Dispose() + + protected override void OnClose() { LayerProperty.KeyframesToggled -= LayerPropertyOnKeyframesToggled; LayerProperty.KeyframeAdded -= LayerPropertyOnKeyframeAdded; LayerProperty.KeyframeRemoved -= LayerPropertyOnKeyframeRemoved; + + base.OnClose(); + } + + protected override void OnInitialActivate() + { + LayerProperty.KeyframesToggled += LayerPropertyOnKeyframesToggled; + LayerProperty.KeyframeAdded += LayerPropertyOnKeyframeAdded; + LayerProperty.KeyframeRemoved += LayerPropertyOnKeyframeRemoved; + UpdateKeyframes(); + + base.OnInitialActivate(); } private void LayerPropertyOnKeyframesToggled(object sender, LayerPropertyEventArgs e) @@ -92,14 +99,10 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline if (LayerProperty.KeyframesEnabled) { List> keyframes = LayerProperty.Keyframes.ToList(); - List> toRemove = Items.Where(t => !keyframes.Contains(t.LayerPropertyKeyframe)).ToList(); - foreach (TimelineKeyframeViewModel timelineKeyframeViewModel in toRemove) - timelineKeyframeViewModel.Dispose(); - Items.RemoveRange(toRemove); - Items.AddRange(keyframes - .Where(k => Items.All(t => t.LayerPropertyKeyframe != k)) - .Select(k => new TimelineKeyframeViewModel(k, _profileEditorService)) + Items.RemoveRange(Items.Where(t => !keyframes.Contains(t.LayerPropertyKeyframe)).ToList()); + Items.AddRange( + keyframes.Where(k => Items.All(t => t.LayerPropertyKeyframe != k)).Select(k => new TimelineKeyframeViewModel(k, _profileEditorService)) ); } else @@ -110,7 +113,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline } } - public interface ITimelinePropertyViewModel : IScreen, IDisposable + public interface ITimelinePropertyViewModel : IScreen { List GetAllKeyframeViewModels(); void WipeKeyframes(TimeSpan? start, TimeSpan? end); diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs index 75a795339..96b5a3e10 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs @@ -14,7 +14,7 @@ using Stylet; namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline { - public sealed class TimelineSegmentViewModel : Screen, IDisposable + public sealed class TimelineSegmentViewModel : Screen { private readonly IDialogService _dialogService; private bool _draggingSegment; @@ -28,7 +28,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline private bool _showRepeatButton; private bool _showSegmentName; - public TimelineSegmentViewModel(SegmentViewModelType segment, BindableCollection layerPropertyGroups, + public TimelineSegmentViewModel(SegmentViewModelType segment, IObservableCollection layerPropertyGroups, IProfileEditorService profileEditorService, IDialogService dialogService) { _dialogService = dialogService; @@ -43,18 +43,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline else if (Segment == SegmentViewModelType.End) ToolTip = "This segment is played once a condition is no longer met"; IsMainSegment = Segment == SegmentViewModelType.Main; - - ProfileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; - ProfileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected; - if (ProfileEditorService.SelectedProfileElement != null) - ProfileEditorService.SelectedProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged; - - Update(); } public RenderProfileElement SelectedProfileElement => ProfileEditorService.SelectedProfileElement; public SegmentViewModelType Segment { get; } - public BindableCollection LayerPropertyGroups { get; } + public IObservableCollection LayerPropertyGroups { get; } public IProfileEditorService ProfileEditorService { get; } public string ToolTip { get; } @@ -160,14 +153,28 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline layerPropertyGroupViewModel.ShiftKeyframes(start, end, amount); } - #region IDIsposable + #region Overrides of Screen - public void Dispose() + /// + protected override void OnInitialActivate() + { + ProfileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; + ProfileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected; + if (ProfileEditorService.SelectedProfileElement != null) + ProfileEditorService.SelectedProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged; + + Update(); + base.OnInitialActivate(); + } + + /// + protected override void OnClose() { ProfileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged; ProfileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected; if (SelectedProfileElement != null) SelectedProfileElement.Timeline.PropertyChanged -= TimelineOnPropertyChanged; + base.OnClose(); } #endregion diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs index 8fd0acb09..eb3f728a8 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs @@ -11,33 +11,26 @@ using Artemis.Core; using Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline.Models; using Artemis.UI.Shared; using Artemis.UI.Shared.Services; -using Artemis.UI.Shared.Services.Models; using Stylet; namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline { - public sealed class TimelineViewModel : Screen, IDisposable + public sealed class TimelineViewModel : Screen { private readonly IProfileEditorService _profileEditorService; private RectangleGeometry _selectionRectangle; - public TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection layerPropertyGroups, IProfileEditorService profileEditorService) + public TimelineViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IObservableCollection layerPropertyGroups, IProfileEditorService profileEditorService) { _profileEditorService = profileEditorService; LayerPropertiesViewModel = layerPropertiesViewModel; LayerPropertyGroups = layerPropertyGroups; SelectionRectangle = new RectangleGeometry(); - - _profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; - _profileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected; - if (_profileEditorService.SelectedProfileElement != null) - _profileEditorService.SelectedProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged; - Update(); } public LayerPropertiesViewModel LayerPropertiesViewModel { get; } - public BindableCollection LayerPropertyGroups { get; } + public IObservableCollection LayerPropertyGroups { get; } public RectangleGeometry SelectionRectangle { @@ -101,14 +94,27 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Timeline Update(); } - #region IDisposable + #region Overrides of Screen - public void Dispose() + /// + protected override void OnInitialActivate() + { + _profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged; + _profileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected; + if (_profileEditorService.SelectedProfileElement != null) + _profileEditorService.SelectedProfileElement.Timeline.PropertyChanged += TimelineOnPropertyChanged; + Update(); + base.OnInitialActivate(); + } + + /// + protected override void OnClose() { _profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged; _profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected; if (_profileEditorService.SelectedProfileElement != null) _profileEditorService.SelectedProfileElement.Timeline.PropertyChanged -= TimelineOnPropertyChanged; + base.OnClose(); } #endregion diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeGroupView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeGroupView.xaml index 9e4ce273f..0e6d576d7 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeGroupView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeGroupView.xaml @@ -224,7 +224,7 @@ Do not bind directly to the LayerPropertyGroupViewModel.Children collection Instead use a reference provided by the VM that is null when collapsed, virtualization for noobs --> - Children => - LayerPropertyGroupViewModel.IsExpanded && LayerPropertyGroupViewModel.IsVisible - ? LayerPropertyGroupViewModel.Children - : null; + public IObservableCollection Items => LayerPropertyGroupViewModel.IsExpanded && + LayerPropertyGroupViewModel.IsVisible + ? LayerPropertyGroupViewModel.Items + : null; public void OpenBrushSettings() { @@ -164,7 +155,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree private void LayerPropertyGroupViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(LayerPropertyGroupViewModel.IsExpanded) || e.PropertyName == nameof(LayerPropertyGroupViewModel.IsVisible)) - NotifyOfPropertyChange(nameof(Children)); + NotifyOfPropertyChange(nameof(Items)); } private void DetermineGroupType() @@ -180,5 +171,23 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree else GroupType = LayerPropertyGroupType.None; } + + #region Overrides of Screen + + /// + protected override void OnInitialActivate() + { + LayerPropertyGroupViewModel.PropertyChanged += LayerPropertyGroupViewModelOnPropertyChanged; + base.OnInitialActivate(); + } + + /// + protected override void OnClose() + { + LayerPropertyGroupViewModel.PropertyChanged -= LayerPropertyGroupViewModelOnPropertyChanged; + base.OnClose(); + } + + #endregion } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs index 212c23273..d216d8690 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs @@ -19,12 +19,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree LayerPropertyViewModel = layerPropertyViewModel; PropertyInputViewModel = _profileEditorService.CreatePropertyInputViewModel(LayerProperty); - _profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged; - LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged; - LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange; - LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange; - LayerProperty.KeyframesToggled += LayerPropertyOnKeyframesToggled; - LayerPropertyViewModel.IsVisible = !LayerProperty.IsHidden; + PropertyInputViewModel.ConductWith(this); } public LayerProperty LayerProperty { get; } @@ -89,19 +84,30 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree return depth; } + + #region Overrides of Screen - public bool HasPropertyInputViewModel => PropertyInputViewModel != null; - - #region IDisposable - - public void Dispose() + /// + protected override void OnInitialActivate() + { + _profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged; + LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged; + LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange; + LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange; + LayerProperty.KeyframesToggled += LayerPropertyOnKeyframesToggled; + LayerPropertyViewModel.IsVisible = !LayerProperty.IsHidden; + base.OnInitialActivate(); + } + + /// + protected override void OnClose() { - _propertyInputViewModel?.Dispose(); _profileEditorService.SelectedDataBindingChanged -= ProfileEditorServiceOnSelectedDataBindingChanged; LayerProperty.VisibilityChanged -= LayerPropertyOnVisibilityChanged; LayerProperty.DataBindingEnabled -= LayerPropertyOnDataBindingChange; LayerProperty.DataBindingDisabled -= LayerPropertyOnDataBindingChange; LayerProperty.KeyframesToggled -= LayerPropertyOnKeyframesToggled; + base.OnClose(); } #endregion @@ -131,9 +137,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree #endregion } - public interface ITreePropertyViewModel : IScreen, IDisposable + public interface ITreePropertyViewModel : IScreen { - bool HasPropertyInputViewModel { get; } bool HasDataBinding { get; } double GetDepth(); } diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs index 658226339..70bbedc99 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeViewModel.cs @@ -7,7 +7,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree { public class TreeViewModel : Screen { - public TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, BindableCollection layerPropertyGroups) + public TreeViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IObservableCollection layerPropertyGroups) { LayerPropertiesViewModel = layerPropertiesViewModel; @@ -16,7 +16,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree } public LayerPropertiesViewModel LayerPropertiesViewModel { get; } - public BindableCollection LayerPropertyGroups { get; } + public IObservableCollection LayerPropertyGroups { get; } public void PropertyTreePreviewMouseWheel(object sender, MouseWheelEventArgs e) { diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs index 3812e8c35..d5d43ed53 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs @@ -15,12 +15,11 @@ using Artemis.UI.Screens.ProfileEditor.ProfileTree; using Artemis.UI.Screens.ProfileEditor.Visualization; using Artemis.UI.Shared.Services; using MaterialDesignThemes.Wpf; -using Newtonsoft.Json; using Stylet; namespace Artemis.UI.Screens.ProfileEditor { - public class ProfileEditorViewModel : Conductor.Collection.AllActive + public class ProfileEditorViewModel : Screen { private readonly IModuleService _moduleService; private readonly IProfileEditorService _profileEditorService; @@ -64,14 +63,13 @@ namespace Artemis.UI.Screens.ProfileEditor // Populate the panels ProfileViewModel = profileViewModel; + ProfileViewModel.ConductWith(this); ProfileTreeViewModel = profileTreeViewModel; + ProfileTreeViewModel.ConductWith(this); DisplayConditionsViewModel = dataModelConditionsViewModel; + DisplayConditionsViewModel.ConductWith(this); LayerPropertiesViewModel = layerPropertiesViewModel; - - Items.Add(ProfileViewModel); - Items.Add(ProfileTreeViewModel); - Items.Add(dataModelConditionsViewModel); - Items.Add(LayerPropertiesViewModel); + LayerPropertiesViewModel.ConductWith(this); } public ProfileModule Module { get; } diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/CanvasViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/CanvasViewModel.cs index a5a719060..4419a108f 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/CanvasViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/CanvasViewModel.cs @@ -1,9 +1,8 @@ -using System; -using Stylet; +using Stylet; namespace Artemis.UI.Screens.ProfileEditor.Visualization { - public abstract class CanvasViewModel : PropertyChangedBase, IDisposable + public abstract class CanvasViewModel : Screen { private double _x; private double _y; @@ -19,18 +18,5 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization get => _y; set => SetAndNotify(ref _y, value); } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - } - } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileLayerViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileLayerViewModel.cs index 7af191dec..7aea3591f 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileLayerViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileLayerViewModel.cs @@ -5,9 +5,9 @@ using System.Windows; using System.Windows.Media; using Artemis.Core; using Artemis.UI.Extensions; +using Artemis.UI.Screens.Shared; using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services; -using Stylet; namespace Artemis.UI.Screens.ProfileEditor.Visualization { @@ -15,25 +15,17 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization { private readonly ILayerEditorService _layerEditorService; private readonly IProfileEditorService _profileEditorService; - private readonly ProfileViewModel _profileViewModel; + private readonly PanZoomViewModel _panZoomViewModel; private bool _isSelected; private Geometry _shapeGeometry; private Rect _viewportRectangle; - public ProfileLayerViewModel(Layer layer, ProfileViewModel profileViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService) + public ProfileLayerViewModel(Layer layer, PanZoomViewModel panZoomViewModel, IProfileEditorService profileEditorService, ILayerEditorService layerEditorService) { - _profileViewModel = profileViewModel; + _panZoomViewModel = panZoomViewModel; _profileEditorService = profileEditorService; _layerEditorService = layerEditorService; Layer = layer; - - - Update(); - Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated; - _profileEditorService.ProfileElementSelected += OnProfileElementSelected; - _profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated; - _profileEditorService.ProfilePreviewUpdated += ProfileEditorServiceOnProfilePreviewUpdated; - _profileViewModel.PanZoomViewModel.PropertyChanged += PanZoomViewModelOnPropertyChanged; } public Layer Layer { get; } @@ -59,8 +51,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization get { if (IsSelected) - return Math.Max(2 / _profileViewModel.PanZoomViewModel.Zoom, 1); - return Math.Max(2 / _profileViewModel.PanZoomViewModel.Zoom, 1) / 2; + return Math.Max(2 / _panZoomViewModel.Zoom, 1); + return Math.Max(2 / _panZoomViewModel.Zoom, 1) / 2; } } @@ -86,23 +78,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization } } - protected override void Dispose(bool disposing) - { - if (disposing) - { - Layer.RenderPropertiesUpdated -= LayerOnRenderPropertiesUpdated; - _profileEditorService.ProfileElementSelected -= OnProfileElementSelected; - _profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated; - _profileEditorService.ProfilePreviewUpdated -= ProfileEditorServiceOnProfilePreviewUpdated; - _profileViewModel.PanZoomViewModel.PropertyChanged -= PanZoomViewModelOnPropertyChanged; - } - - base.Dispose(disposing); - } - private void PanZoomViewModelOnPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(_profileViewModel.PanZoomViewModel.Zoom)) + if (e.PropertyName == nameof(_panZoomViewModel.Zoom)) { NotifyOfPropertyChange(nameof(StrokeThickness)); NotifyOfPropertyChange(nameof(LayerStrokeThickness)); @@ -193,6 +171,33 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization } } + #region Overrides of Screen + + /// + protected override void OnInitialActivate() + { + Update(); + Layer.RenderPropertiesUpdated += LayerOnRenderPropertiesUpdated; + _profileEditorService.ProfileElementSelected += OnProfileElementSelected; + _profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated; + _profileEditorService.ProfilePreviewUpdated += ProfileEditorServiceOnProfilePreviewUpdated; + _panZoomViewModel.PropertyChanged += PanZoomViewModelOnPropertyChanged; + base.OnInitialActivate(); + } + + /// + protected override void OnClose() + { + Layer.RenderPropertiesUpdated -= LayerOnRenderPropertiesUpdated; + _profileEditorService.ProfileElementSelected -= OnProfileElementSelected; + _profileEditorService.SelectedProfileElementUpdated -= OnSelectedProfileElementUpdated; + _profileEditorService.ProfilePreviewUpdated -= ProfileEditorServiceOnProfilePreviewUpdated; + _panZoomViewModel.PropertyChanged -= PanZoomViewModelOnPropertyChanged; + base.OnClose(); + } + + #endregion + #region Event handlers private void LayerOnRenderPropertiesUpdated(object sender, EventArgs e) diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileView.xaml b/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileView.xaml index a9314aa0b..1237727f8 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileView.xaml @@ -106,7 +106,7 @@ - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileViewModel.cs index 25958a2c2..6684c3bfe 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileViewModel.cs @@ -15,7 +15,7 @@ using Stylet; namespace Artemis.UI.Screens.ProfileEditor.Visualization { - public class ProfileViewModel : Screen, IProfileEditorPanelViewModel, IHandle, IHandle + public class ProfileViewModel : Conductor.Collection.AllActive, IProfileEditorPanelViewModel, IHandle, IHandle { private readonly IProfileEditorService _profileEditorService; private readonly ICoreService _coreService; @@ -28,7 +28,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization private VisualizationToolViewModel _activeToolViewModel; private bool _canApplyToLayer; private bool _canSelectEditTool; - private BindableCollection _canvasViewModels; private BindableCollection _devices; private BindableCollection _highlightedLeds; private PluginSetting _highlightSelectedLayer; @@ -36,7 +35,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization private PanZoomViewModel _panZoomViewModel; private Layer _previousSelectedLayer; private int _previousTool; - private BindableCollection _selectedLeds; private DateTime _lastUpdate; public ProfileViewModel(IProfileEditorService profileEditorService, @@ -54,22 +52,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization _visualizationToolVmFactory = visualizationToolVmFactory; _profileLayerVmFactory = profileLayerVmFactory; - Execute.OnUIThreadSync(() => - { - PanZoomViewModel = new PanZoomViewModel {LimitToZero = false}; - - CanvasViewModels = new BindableCollection(); - Devices = new BindableCollection(); - HighlightedLeds = new BindableCollection(); - SelectedLeds = new BindableCollection(); - }); - - ApplySurfaceConfiguration(_surfaceService.ActiveSurface); - ActivateToolByIndex(0); - eventAggregator.Subscribe(this); } + public bool CanSelectEditTool { get => _canSelectEditTool; @@ -82,12 +68,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization set => SetAndNotify(ref _panZoomViewModel, value); } - public BindableCollection CanvasViewModels - { - get => _canvasViewModels; - set => SetAndNotify(ref _canvasViewModels, value); - } - public BindableCollection Devices { get => _devices; @@ -100,12 +80,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization set => SetAndNotify(ref _highlightedLeds, value); } - public BindableCollection SelectedLeds - { - get => _selectedLeds; - set => SetAndNotify(ref _selectedLeds, value); - } - public PluginSetting AlwaysApplyDataBindings { get => _alwaysApplyDataBindings; @@ -126,10 +100,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization // Remove the tool from the canvas if (_activeToolViewModel != null) { - lock (CanvasViewModels) + lock (Items) { - CanvasViewModels.Remove(_activeToolViewModel); - NotifyOfPropertyChange(() => CanvasViewModels); + Items.Remove(_activeToolViewModel); + NotifyOfPropertyChange(() => Items); } } @@ -138,10 +112,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization // Add the new tool to the canvas if (_activeToolViewModel != null) { - lock (CanvasViewModels) + lock (Items) { - CanvasViewModels.Add(_activeToolViewModel); - NotifyOfPropertyChange(() => CanvasViewModels); + Items.Add(_activeToolViewModel); + NotifyOfPropertyChange(() => Items); } } } @@ -163,15 +137,16 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization set => SetAndNotify(ref _canApplyToLayer, value); } - public List GetLedsInRectangle(Rect selectedRect) - { - return Devices.SelectMany(d => d.Leds) - .Where(led => led.RgbLed.AbsoluteLedRectangle.ToWindowsRect(1).IntersectsWith(selectedRect)) - .ToList(); - } - protected override void OnInitialActivate() { + PanZoomViewModel = new PanZoomViewModel {LimitToZero = false}; + + Devices = new BindableCollection(); + HighlightedLeds = new BindableCollection(); + + ApplySurfaceConfiguration(_surfaceService.ActiveSurface); + ActivateToolByIndex(0); + ApplyActiveProfile(); AlwaysApplyDataBindings = _settingsService.GetSetting("ProfileEditor.AlwaysApplyDataBindings", true); @@ -203,10 +178,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization AlwaysApplyDataBindings.Save(); HighlightSelectedLayer.Save(); - foreach (CanvasViewModel canvasViewModel in CanvasViewModels) - canvasViewModel.Dispose(); - CanvasViewModels.Clear(); - base.OnClose(); } @@ -217,23 +188,20 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization private void ApplyActiveProfile() { - List layerViewModels = CanvasViewModels.Where(vm => vm is ProfileLayerViewModel).Cast().ToList(); + List layerViewModels = Items.Where(vm => vm is ProfileLayerViewModel).Cast().ToList(); List layers = _profileEditorService.SelectedProfile?.GetAllLayers() ?? new List(); // Add new layers missing a VM foreach (Layer layer in layers) { if (layerViewModels.All(vm => vm.Layer != layer)) - CanvasViewModels.Add(_profileLayerVmFactory.Create(layer, this)); + Items.Add(_profileLayerVmFactory.Create(layer, PanZoomViewModel)); } // Remove layers that no longer exist IEnumerable toRemove = layerViewModels.Where(vm => !layers.Contains(vm.Layer)); foreach (ProfileLayerViewModel profileLayerViewModel in toRemove) - { - profileLayerViewModel.Dispose(); - CanvasViewModels.Remove(profileLayerViewModel); - } + Items.Remove(profileLayerViewModel); } private void ApplySurfaceConfiguration(ArtemisSurface surface) @@ -270,20 +238,19 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization private void ActivateToolByIndex(int value) { - // Consider using DI if dependencies start to add up switch (value) { case 0: - ActiveToolViewModel = _visualizationToolVmFactory.ViewpointMoveToolViewModel(this); + ActiveToolViewModel = _visualizationToolVmFactory.ViewpointMoveToolViewModel(PanZoomViewModel); break; case 1: - ActiveToolViewModel = _visualizationToolVmFactory.EditToolViewModel(this); + ActiveToolViewModel = _visualizationToolVmFactory.EditToolViewModel(PanZoomViewModel); break; case 2: - ActiveToolViewModel = _visualizationToolVmFactory.SelectionToolViewModel(this); + ActiveToolViewModel = _visualizationToolVmFactory.SelectionToolViewModel(PanZoomViewModel); break; case 3: - ActiveToolViewModel = _visualizationToolVmFactory.SelectionRemoveToolViewModel(this); + ActiveToolViewModel = _visualizationToolVmFactory.SelectionRemoveToolViewModel(PanZoomViewModel); break; } @@ -324,43 +291,6 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization #endregion - #region Context menu actions - - public void CreateLayer() - { - } - - public void ApplyToLayer() - { - if (!(_profileEditorService.SelectedProfileElement is Layer layer)) - return; - - layer.ClearLeds(); - layer.AddLeds(SelectedLeds); - - _profileEditorService.UpdateSelectedProfileElement(); - } - - public void SelectAll() - { - SelectedLeds.Clear(); - SelectedLeds.AddRange(Devices.SelectMany(d => d.Leds)); - } - - public void InverseSelection() - { - List current = SelectedLeds.ToList(); - SelectedLeds.Clear(); - SelectedLeds.AddRange(Devices.SelectMany(d => d.Leds).Except(current)); - } - - public void ClearSelection() - { - SelectedLeds.Clear(); - } - - #endregion - #region Event handlers private void OnFrameRendered(object sender, FrameRenderedEventArgs e) @@ -368,7 +298,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization TimeSpan delta = DateTime.Now - _lastUpdate; _lastUpdate = DateTime.Now; - if (!AlwaysApplyDataBindings.Value || _profileEditorService.SelectedProfile == null || ((ProfileEditorViewModel) Parent).LayerPropertiesViewModel.Playing) + if (!AlwaysApplyDataBindings.Value || _profileEditorService.SelectedProfile == null || _profileEditorService.Playing) return; foreach (IDataBindingRegistration dataBindingRegistration in _profileEditorService.SelectedProfile.GetAllFolders() diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/EditToolView.xaml b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/EditToolView.xaml index d184d1b06..bc9fcf3d4 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/EditToolView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/EditToolView.xaml @@ -11,7 +11,7 @@ d:DesignWidth="800" d:DataContext="{d:DesignInstance {x:Type tools:EditToolViewModel}}"> - Update(); - profileEditorService.ProfileElementSelected += (sender, args) => Update(); - profileEditorService.SelectedProfileElementUpdated += (sender, args) => Update(); - profileEditorService.ProfilePreviewUpdated += (sender, args) => Update(); } public SKPath ShapePath @@ -60,12 +56,12 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools ShapePath = _layerEditorService.GetLayerPath(layer, true, true, true); ShapeAnchor = _layerEditorService.GetLayerAnchorPosition(layer).ToSKPoint(); + + Rect layerBounds = _layerEditorService.GetLayerBounds(layer); + TransformGroup layerTransformGroup = _layerEditorService.GetLayerTransformGroup(layer); Execute.PostToUIThread(() => { - RectangleGeometry shapeGeometry = new(_layerEditorService.GetLayerBounds(layer)) - { - Transform = _layerEditorService.GetLayerTransformGroup(layer) - }; + RectangleGeometry shapeGeometry = new(layerBounds) {Transform = layerTransformGroup}; shapeGeometry.Freeze(); ShapeGeometry = shapeGeometry; }); @@ -74,6 +70,37 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools _topLeft = _layerEditorService.GetLayerPath(layer, true, true, true).Points[0]; } + #region Overrides of Screen + + /// + protected override void OnInitialActivate() + { + ProfileEditorService.ProfileSelected += UpdateEventHandler; + ProfileEditorService.ProfileElementSelected += UpdateEventHandler; + ProfileEditorService.SelectedProfileElementUpdated += UpdateEventHandler; + ProfileEditorService.ProfilePreviewUpdated += UpdateEventHandler; + + Update(); + base.OnInitialActivate(); + } + + private void UpdateEventHandler(object sender, EventArgs e) + { + Update(); + } + + /// + protected override void OnClose() + { + ProfileEditorService.ProfileSelected -= UpdateEventHandler; + ProfileEditorService.ProfileElementSelected -= UpdateEventHandler; + ProfileEditorService.SelectedProfileElementUpdated -= UpdateEventHandler; + ProfileEditorService.ProfilePreviewUpdated -= UpdateEventHandler; + base.OnClose(); + } + + #endregion + #region Rotation private bool _rotating; diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs index bcb18e5eb..f5a823ba0 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/SelectionRemoveToolViewModel.cs @@ -5,6 +5,7 @@ using System.Windows; using System.Windows.Input; using Artemis.Core; using Artemis.UI.Properties; +using Artemis.UI.Screens.Shared; using Artemis.UI.Shared.Services; namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools @@ -13,7 +14,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools { private Rect _dragRectangle; - public SelectionRemoveToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + public SelectionRemoveToolViewModel(PanZoomViewModel panZoomViewModel, IProfileEditorService profileEditorService) : base(panZoomViewModel, profileEditorService) { using (MemoryStream stream = new(Resources.aero_pen_min)) { @@ -31,13 +32,11 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools { base.MouseUp(sender, e); - Point position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e); + Point position = PanZoomViewModel.GetRelativeMousePosition(sender, e); Rect selectedRect = new(MouseDownStartPosition, position); // Get selected LEDs - List selectedLeds = ProfileViewModel.GetLedsInRectangle(selectedRect); - ProfileViewModel.SelectedLeds.Clear(); - ProfileViewModel.SelectedLeds.AddRange(selectedLeds); + List selectedLeds = ProfileEditorService.GetLedsInRectangle(selectedRect); // Apply the selection to the selected layer layer if (ProfileEditorService.SelectedProfileElement is Layer layer) @@ -59,15 +58,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools return; } - Point position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e); + Point position = PanZoomViewModel.GetRelativeMousePosition(sender, e); Rect selectedRect = new(MouseDownStartPosition, position); - List selectedLeds = ProfileViewModel.GetLedsInRectangle(selectedRect); - - // Unless shift is held down, clear the current selection - if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) - ProfileViewModel.SelectedLeds.Clear(); - ProfileViewModel.SelectedLeds.AddRange(selectedLeds.Except(ProfileViewModel.SelectedLeds)); - DragRectangle = selectedRect; } } diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs index 7a3edccd6..d6e5c17d6 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/SelectionToolViewModel.cs @@ -7,6 +7,7 @@ using Artemis.Core; using Artemis.Core.LayerBrushes; using Artemis.Core.Services; using Artemis.UI.Properties; +using Artemis.UI.Screens.Shared; using Artemis.UI.Shared.Services; namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools @@ -16,9 +17,8 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools private readonly ILayerBrushService _layerBrushService; private Rect _dragRectangle; - public SelectionToolViewModel(ProfileViewModel profileViewModel, - IProfileEditorService profileEditorService, - ILayerBrushService layerBrushService) : base(profileViewModel, profileEditorService) + public SelectionToolViewModel(PanZoomViewModel panZoomViewModel, IProfileEditorService profileEditorService, ILayerBrushService layerBrushService) + : base(panZoomViewModel, profileEditorService) { _layerBrushService = layerBrushService; using (MemoryStream stream = new(Resources.aero_crosshair)) @@ -37,11 +37,11 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools { base.MouseUp(sender, e); - Point position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e); + Point position = PanZoomViewModel.GetRelativeMousePosition(sender, e); Rect selectedRect = new(MouseDownStartPosition, position); // Get selected LEDs - List selectedLeds = ProfileViewModel.GetLedsInRectangle(selectedRect); + List selectedLeds = ProfileEditorService.GetLedsInRectangle(selectedRect); // Apply the selection to the selected layer layer if (ProfileEditorService.SelectedProfileElement is Layer layer) @@ -77,14 +77,9 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools return; } - Point position = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e); + Point position = PanZoomViewModel.GetRelativeMousePosition(sender, e); Rect selectedRect = new(MouseDownStartPosition, position); - List selectedLeds = ProfileViewModel.GetLedsInRectangle(selectedRect); - - // Unless shift is held down, clear the current selection - if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) - ProfileViewModel.SelectedLeds.Clear(); - ProfileViewModel.SelectedLeds.AddRange(selectedLeds.Except(ProfileViewModel.SelectedLeds)); + List selectedLeds = ProfileEditorService.GetLedsInRectangle(selectedRect); DragRectangle = selectedRect; } diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs index 5a795bbc3..269b0f92f 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/ViewpointMoveToolViewModel.cs @@ -1,20 +1,21 @@ using System.Windows.Input; +using Artemis.UI.Screens.Shared; using Artemis.UI.Shared.Services; namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools { public class ViewpointMoveToolViewModel : VisualizationToolViewModel { - public ViewpointMoveToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) : base(profileViewModel, profileEditorService) + public ViewpointMoveToolViewModel(PanZoomViewModel panZoomViewModel, IProfileEditorService profileEditorService) : base(panZoomViewModel, profileEditorService) { Cursor = Cursors.Hand; - ProfileViewModel.PanZoomViewModel.LastPanPosition = null; + PanZoomViewModel.LastPanPosition = null; } public override void MouseMove(object sender, MouseEventArgs e) { base.MouseMove(sender, e); - ProfileViewModel.PanZoomViewModel.ProcessMouseMove(sender, e); + PanZoomViewModel.ProcessMouseMove(sender, e); } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs index f14e433c7..722b35513 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/VisualizationToolViewModel.cs @@ -1,6 +1,9 @@ using System; +using System.Collections.Generic; using System.Windows; using System.Windows.Input; +using Artemis.Core; +using Artemis.UI.Screens.Shared; using Artemis.UI.Shared.Services; namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools @@ -11,18 +14,18 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools private bool _isMouseDown; private Point _mouseDownStartPosition; - protected VisualizationToolViewModel(ProfileViewModel profileViewModel, IProfileEditorService profileEditorService) + protected VisualizationToolViewModel(PanZoomViewModel panZoomViewModel, IProfileEditorService profileEditorService) { // Not relevant for visualization tools as they overlay the entire canvas X = 0; Y = 0; - ProfileViewModel = profileViewModel; + PanZoomViewModel = panZoomViewModel; ProfileEditorService = profileEditorService; Cursor = Cursors.Arrow; } - public ProfileViewModel ProfileViewModel { get; } + public PanZoomViewModel PanZoomViewModel { get; } public IProfileEditorService ProfileEditorService { get; } public Cursor Cursor @@ -46,7 +49,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools public virtual void MouseDown(object sender, MouseButtonEventArgs e) { IsMouseDown = true; - MouseDownStartPosition = ProfileViewModel.PanZoomViewModel.GetRelativeMousePosition(sender, e); + MouseDownStartPosition = PanZoomViewModel.GetRelativeMousePosition(sender, e); } public virtual void MouseUp(object sender, MouseButtonEventArgs e) diff --git a/src/Artemis.UI/Screens/RootViewModel.cs b/src/Artemis.UI/Screens/RootViewModel.cs index 2ced26ce7..05b57b22c 100644 --- a/src/Artemis.UI/Screens/RootViewModel.cs +++ b/src/Artemis.UI/Screens/RootViewModel.cs @@ -64,7 +64,6 @@ namespace Artemis.UI.Screens _builtInRegistrationService = builtInRegistrationService; _snackbarMessageQueue = snackbarMessageQueue; _sidebarViewModel = sidebarViewModel; - _frameTimeUpdateTimer = new Timer(500); _colorScheme = _settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic); @@ -73,6 +72,8 @@ namespace Artemis.UI.Screens _themeWatcher = new ThemeWatcher(); ApplyColorSchemeSetting(); + _sidebarViewModel.ConductWith(this); + ActiveItem = sidebarViewModel.SelectedItem; ActiveItemReady = true; PinSidebar = _settingsService.GetSetting("UI.PinSidebar", false); @@ -334,7 +335,6 @@ namespace Artemis.UI.Screens GC.Collect(); }); - base.OnClose(); } diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs index 70d14ed5d..3cbf3c712 100644 --- a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs +++ b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs @@ -22,13 +22,13 @@ using Stylet; namespace Artemis.UI.Screens.Sidebar { - public sealed class SidebarViewModel : PropertyChangedBase, IHandle, IDisposable + public sealed class SidebarViewModel : Screen, IHandle, IDisposable { private readonly Timer _activeModulesUpdateTimer; private readonly IKernel _kernel; - private readonly ISettingsService _settingsService; private readonly IModuleVmFactory _moduleVmFactory; private readonly IPluginManagementService _pluginManagementService; + private readonly IModuleService _moduleService; private string _activeModules; private bool _isSidebarOpen; private IScreen _selectedItem; @@ -38,9 +38,9 @@ namespace Artemis.UI.Screens.Sidebar public SidebarViewModel(IKernel kernel, ISettingsService settingsService, IEventAggregator eventAggregator, IModuleVmFactory moduleVmFactory, IPluginManagementService pluginManagementService, IModuleService moduleService) { _kernel = kernel; - _settingsService = settingsService; _moduleVmFactory = moduleVmFactory; _pluginManagementService = pluginManagementService; + _moduleService = moduleService; SidebarModules = new Dictionary(); SidebarItems = new BindableCollection(); @@ -48,14 +48,6 @@ namespace Artemis.UI.Screens.Sidebar PinSidebar.AutoSave = true; _activeModulesUpdateTimer = new Timer(1000); - _activeModulesUpdateTimer.Start(); - _activeModulesUpdateTimer.Elapsed += ActiveModulesUpdateTimerOnElapsed; - - _pluginManagementService.PluginFeatureEnabled += OnFeatureEnabled; - _pluginManagementService.PluginFeatureDisabled += OnFeatureDisabled; - moduleService.ModulePriorityUpdated += OnModulePriorityUpdated; - - SetupSidebar(); eventAggregator.Subscribe(this); } @@ -250,5 +242,36 @@ namespace Artemis.UI.Screens.Sidebar } #endregion + + #region Overrides of Screen + + /// + protected override void OnInitialActivate() + { + _activeModulesUpdateTimer.Start(); + _activeModulesUpdateTimer.Elapsed += ActiveModulesUpdateTimerOnElapsed; + + _pluginManagementService.PluginFeatureEnabled += OnFeatureEnabled; + _pluginManagementService.PluginFeatureDisabled += OnFeatureDisabled; + _moduleService.ModulePriorityUpdated += OnModulePriorityUpdated; + + SetupSidebar(); + + base.OnInitialActivate(); + } + + /// + protected override void OnClose() + { + _activeModulesUpdateTimer.Stop(); + _activeModulesUpdateTimer.Elapsed -= ActiveModulesUpdateTimerOnElapsed; + + _pluginManagementService.PluginFeatureEnabled -= OnFeatureEnabled; + _pluginManagementService.PluginFeatureDisabled -= OnFeatureDisabled; + _moduleService.ModulePriorityUpdated -= OnModulePriorityUpdated; + base.OnClose(); + } + + #endregion } } \ No newline at end of file