diff --git a/src/Artemis.Core/Models/Profile/ProfileElement.cs b/src/Artemis.Core/Models/Profile/ProfileElement.cs
index fcdf4bd97..79588e4ae 100644
--- a/src/Artemis.Core/Models/Profile/ProfileElement.cs
+++ b/src/Artemis.Core/Models/Profile/ProfileElement.cs
@@ -146,6 +146,8 @@ namespace Artemis.Core.Models.Profile
child.Parent = this;
}
+
+ OnChildAdded();
}
///
@@ -164,6 +166,8 @@ namespace Artemis.Core.Models.Profile
child.Parent = null;
}
+
+ OnChildRemoved();
}
public override string ToString()
@@ -175,5 +179,22 @@ namespace Artemis.Core.Models.Profile
/// Applies the profile element's properties to the underlying storage entity
///
internal abstract void ApplyToEntity();
+
+ #region Events
+
+ public event EventHandler ChildAdded;
+ public event EventHandler ChildRemoved;
+
+ protected virtual void OnChildAdded()
+ {
+ ChildAdded?.Invoke(this, EventArgs.Empty);
+ }
+
+ protected virtual void OnChildRemoved()
+ {
+ ChildRemoved?.Invoke(this, EventArgs.Empty);
+ }
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs
index c1271a780..6f7ac96c2 100644
--- a/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs
+++ b/src/Artemis.UI.Shared/Controls/DeviceVisualizer.cs
@@ -3,15 +3,12 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
-using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Artemis.Core.Models.Surface;
-using RGB.NET.Core;
-using Size = System.Windows.Size;
namespace Artemis.UI.Shared.Controls
{
@@ -28,9 +25,9 @@ namespace Artemis.UI.Shared.Controls
private readonly DrawingGroup _backingStore;
private readonly List _deviceVisualizerLeds;
+ private readonly DispatcherTimer _timer;
private BitmapImage _deviceImage;
private ArtemisDevice _oldDevice;
- private readonly DispatcherTimer _timer;
public DeviceVisualizer()
{
@@ -41,8 +38,8 @@ namespace Artemis.UI.Shared.Controls
_timer = new DispatcherTimer {Interval = TimeSpan.FromMilliseconds(40)};
_timer.Tick += TimerOnTick;
- Loaded += (sender, args) => _timer.Start();
- Unloaded += (sender, args) => _timer.Stop();
+ Loaded += OnLoaded;
+ Unloaded += OnUnloaded;
}
public ArtemisDevice Device
@@ -117,12 +114,28 @@ namespace Artemis.UI.Shared.Controls
return rotationRect.Size;
}
+ private void OnUnloaded(object sender, RoutedEventArgs e)
+ {
+ _timer.Stop();
+
+ if (_oldDevice != null)
+ {
+ Device.RgbDevice.PropertyChanged -= DevicePropertyChanged;
+ _oldDevice = null;
+ }
+ }
+
+ private void OnLoaded(object sender, RoutedEventArgs e)
+ {
+ _timer.Start();
+ }
+
private void TimerOnTick(object sender, EventArgs e)
{
if (ShowColors && Visibility == Visibility.Visible)
Render();
}
-
+
private void UpdateTransform()
{
InvalidateVisual();
@@ -204,7 +217,7 @@ namespace Artemis.UI.Shared.Controls
if (e.PropertyName == nameof(Device.RgbDevice.Scale) || e.PropertyName == nameof(Device.RgbDevice.Rotation))
UpdateTransform();
}
-
+
private void Render()
{
diff --git a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
index 1d09730f5..4c4d05455 100644
--- a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
@@ -23,8 +23,9 @@ namespace Artemis.UI.Shared.Services
private readonly ILogger _logger;
private readonly List _registeredPropertyEditors;
private TimeSpan _currentTime;
- private TimeSpan _lastUpdateTime;
private int _pixelsPerSecond;
+ private object _selectedProfileLock = new object();
+ private object _selectedProfileElementLock = new object();
public ProfileEditorService(ICoreService coreService, IProfileService profileService, IKernel kernel, ILogger logger)
{
@@ -69,43 +70,55 @@ namespace Artemis.UI.Shared.Services
public void ChangeSelectedProfile(Profile profile)
{
- if (SelectedProfile == profile)
- return;
+ lock (_selectedProfileLock)
+ {
+ if (SelectedProfile == profile)
+ return;
- _logger.Verbose("ChangeSelectedProfile {profile}", profile);
- ChangeSelectedProfileElement(null);
+ _logger.Verbose("ChangeSelectedProfile {profile}", profile);
+ ChangeSelectedProfileElement(null);
- var profileElementEvent = new ProfileEventArgs(profile, SelectedProfile);
- SelectedProfile = profile;
- UpdateProfilePreview();
- OnSelectedProfileChanged(profileElementEvent);
+ var profileElementEvent = new ProfileEventArgs(profile, SelectedProfile);
+ SelectedProfile = profile;
+ UpdateProfilePreview();
+ OnSelectedProfileChanged(profileElementEvent);
+ }
}
public void UpdateSelectedProfile()
{
- _logger.Verbose("UpdateSelectedProfile {profile}", SelectedProfile);
- _profileService.UpdateProfile(SelectedProfile, true);
- UpdateProfilePreview();
- OnSelectedProfileChanged(new ProfileEventArgs(SelectedProfile));
+ lock (_selectedProfileLock)
+ {
+ _logger.Verbose("UpdateSelectedProfile {profile}", SelectedProfile);
+ _profileService.UpdateProfile(SelectedProfile, true);
+ UpdateProfilePreview();
+ OnSelectedProfileChanged(new ProfileEventArgs(SelectedProfile));
+ }
}
public void ChangeSelectedProfileElement(RenderProfileElement profileElement)
{
- if (SelectedProfileElement == profileElement)
- return;
+ lock (_selectedProfileElementLock)
+ {
+ if (SelectedProfileElement == profileElement)
+ return;
- _logger.Verbose("ChangeSelectedProfileElement {profile}", profileElement);
- var profileElementEvent = new RenderProfileElementEventArgs(profileElement, SelectedProfileElement);
- SelectedProfileElement = profileElement;
- OnSelectedProfileElementChanged(profileElementEvent);
+ _logger.Verbose("ChangeSelectedProfileElement {profile}", profileElement);
+ var profileElementEvent = new RenderProfileElementEventArgs(profileElement, SelectedProfileElement);
+ SelectedProfileElement = profileElement;
+ OnSelectedProfileElementChanged(profileElementEvent);
+ }
}
public void UpdateSelectedProfileElement()
{
- _logger.Verbose("UpdateSelectedProfileElement {profile}", SelectedProfileElement);
- _profileService.UpdateProfile(SelectedProfile, true);
- UpdateProfilePreview();
- OnSelectedProfileElementUpdated(new RenderProfileElementEventArgs(SelectedProfileElement));
+ lock (_selectedProfileElementLock)
+ {
+ _logger.Verbose("UpdateSelectedProfileElement {profile}", SelectedProfileElement);
+ _profileService.UpdateProfile(SelectedProfile, true);
+ UpdateProfilePreview();
+ OnSelectedProfileElementUpdated(new RenderProfileElementEventArgs(SelectedProfileElement));
+ }
}
public void UpdateProfilePreview()
@@ -114,12 +127,11 @@ namespace Artemis.UI.Shared.Services
return;
// Stick to the main segment for any element that is not currently selected
- foreach (var folder in SelectedProfile.GetAllFolders())
+ foreach (var folder in SelectedProfile.GetAllFolders())
folder.OverrideProgress(CurrentTime, folder != SelectedProfileElement);
- foreach (var layer in SelectedProfile.GetAllLayers())
+ foreach (var layer in SelectedProfile.GetAllLayers())
layer.OverrideProgress(CurrentTime, layer != SelectedProfileElement);
- _lastUpdateTime = CurrentTime;
OnProfilePreviewUpdated();
}
@@ -225,7 +237,7 @@ namespace Artemis.UI.Shared.Services
{
// Get all visible keyframes
var keyframes = SelectedProfileElement.GetAllKeyframes()
- .Where(k => SelectedProfileElement.IsPropertyGroupExpanded(k.BaseLayerProperty.Parent))
+ .Where(k => k != excludedKeyframe && SelectedProfileElement.IsPropertyGroupExpanded(k.BaseLayerProperty.Parent))
.ToList();
// Find the closest keyframe
diff --git a/src/Artemis.UI/Converters/InverseBooleanConverter.cs b/src/Artemis.UI/Converters/InverseBooleanConverter.cs
index 2052a727b..ae7598871 100644
--- a/src/Artemis.UI/Converters/InverseBooleanConverter.cs
+++ b/src/Artemis.UI/Converters/InverseBooleanConverter.cs
@@ -9,8 +9,7 @@ namespace Artemis.UI.Converters
{
#region IValueConverter Members
- public object Convert(object value, Type targetType, object parameter,
- CultureInfo culture)
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType == typeof(bool))
return !(bool) value;
@@ -20,10 +19,14 @@ namespace Artemis.UI.Converters
throw new InvalidOperationException("The target must be a boolean");
}
- public object ConvertBack(object value, Type targetType, object parameter,
- CultureInfo culture)
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
- throw new NotSupportedException();
+ if (targetType == typeof(bool))
+ return !(bool) value;
+ if (targetType == typeof(bool?))
+ return !(bool?) value;
+
+ throw new InvalidOperationException("The target must be a boolean");
}
#endregion
diff --git a/src/Artemis.UI/PropertyInput/EnumPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/EnumPropertyInputViewModel.cs
index e52a177e5..707efcdd2 100644
--- a/src/Artemis.UI/PropertyInput/EnumPropertyInputViewModel.cs
+++ b/src/Artemis.UI/PropertyInput/EnumPropertyInputViewModel.cs
@@ -4,6 +4,7 @@ using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Shared.PropertyInput;
using Artemis.UI.Shared.Services.Interfaces;
using Artemis.UI.Shared.Utilities;
+using Stylet;
namespace Artemis.UI.PropertyInput
{
@@ -11,9 +12,9 @@ namespace Artemis.UI.PropertyInput
{
public EnumPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService) : base(layerProperty, profileEditorService)
{
- EnumValues = EnumUtilities.GetAllValuesAndDescriptions(typeof(T));
+ EnumValues = new BindableCollection(EnumUtilities.GetAllValuesAndDescriptions(typeof(T)));
}
- public IEnumerable EnumValues { get; }
+ public BindableCollection EnumValues { get; }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupView.xaml
index c1c22c6be..5b8312291 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupView.xaml
@@ -13,30 +13,11 @@
-
-
-
-
+
@@ -127,7 +108,13 @@
-
+
+
+
+
+
+
+
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupViewModel.cs
index 3d64c4334..eb06ec9b2 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionGroupViewModel.cs
@@ -70,7 +70,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
// Remove VMs of effects no longer applied on the layer
var toRemove = Children.Where(c => !DisplayConditionGroup.Children.Contains(c.Model)).ToList();
- Children.RemoveRange(toRemove);
+ // Using RemoveRange breaks our lovely animations
+ foreach (var displayConditionViewModel in toRemove)
+ Children.Remove(displayConditionViewModel);
foreach (var childModel in Model.Children)
{
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateView.xaml
index 9b451960c..c83604a27 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateView.xaml
@@ -20,28 +20,11 @@
-
-
+
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateViewModel.cs
index c6770f62d..8a46eb594 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionPredicateViewModel.cs
@@ -171,13 +171,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
LeftSideDataModel.UpdateRequested += LeftDataModelUpdateRequested;
RightSideDataModel.UpdateRequested += RightDataModelUpdateRequested;
- IsInitialized = true;
Update();
+ IsInitialized = true;
}
public override void Update()
{
- if (!IsInitialized)
+ if (LeftSideDataModel == null || (DisplayConditionPredicate.PredicateType == PredicateType.Dynamic && RightSideDataModel == null))
return;
// If static, only allow selecting properties also supported by input
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml
index aa2ab3d81..fec4b6127 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsView.xaml
@@ -6,10 +6,14 @@
xmlns:local="clr-namespace:Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
+ xmlns:converters="clr-namespace:Artemis.UI.Converters"
x:Class="Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions.DisplayConditionsView"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance {x:Type local:DisplayConditionsViewModel}}">
+
+
+
@@ -29,10 +33,13 @@
- When conditions no longer met
-
-
-
+ On end:
+
+
+
+
@@ -40,16 +47,18 @@
-
+
-
-
+
+
WAIT FOR FINISH
-
-
-
+
+
+
@@ -57,15 +66,15 @@
-
+
-
-
+
+
SKIP
-
-
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs
index 16445dc45..1ff24cd0a 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs
@@ -1,9 +1,11 @@
-using Artemis.Core.Models.Profile;
+using System.Threading.Tasks;
+using Artemis.Core.Models.Profile;
using Artemis.Core.Models.Profile.Conditions;
using Artemis.Storage.Entities.Profile.Abstract;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Events;
using Artemis.UI.Shared.Services.Interfaces;
+using Stylet;
namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
{
@@ -18,7 +20,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
{
_profileEditorService = profileEditorService;
_displayConditionsVmFactory = displayConditionsVmFactory;
- profileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected;
+
}
public DisplayConditionGroupViewModel RootGroup
@@ -42,8 +44,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
return;
RenderProfileElement.AlwaysFinishTimeline = value == 0;
- NotifyOfPropertyChange(nameof(ConditionBehaviourIndex));
-
_profileEditorService.UpdateSelectedProfileElement();
}
}
@@ -70,5 +70,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.DisplayConditions
RootGroup.IsRootGroup = true;
RootGroup.Update();
}
+
+ protected override void OnActivate()
+ {
+ _profileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected;
+ }
+
+ protected override void OnDeactivate()
+ {
+ _profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected;
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs
index 75613d333..6cfb11aed 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Abstract/LayerPropertyBaseViewModel.cs
@@ -8,11 +8,11 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract
public abstract class LayerPropertyBaseViewModel : PropertyChangedBase, IDisposable
{
private bool _isExpanded;
- private List _children;
+ private BindableCollection _children;
protected LayerPropertyBaseViewModel()
{
- Children = new List();
+ Children = new BindableCollection();
}
public abstract bool IsVisible { get; }
@@ -23,7 +23,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract
set => SetAndNotify(ref _isExpanded, value);
}
- public List Children
+ public BindableCollection Children
{
get => _children;
set => SetAndNotify(ref _children, value);
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
index c708e5fd1..bccd7ee86 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/LayerPropertiesViewModel.cs
@@ -164,6 +164,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
ProfileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
PopulateProperties(null);
+
+ TimelineViewModel?.Dispose();
+ TimelineViewModel = null;
+ StartTimelineSegmentViewModel?.Dispose();
+ StartTimelineSegmentViewModel = null;
+ MainTimelineSegmentViewModel?.Dispose();
+ MainTimelineSegmentViewModel = null;
+ EndTimelineSegmentViewModel?.Dispose();
+ EndTimelineSegmentViewModel = null;
+
base.OnClose();
}
@@ -256,9 +266,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties
ApplyLayerBrush();
ApplyEffects();
}
-
-
-
+
private void SelectedLayerOnLayerBrushUpdated(object sender, EventArgs e)
{
ApplyLayerBrush();
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs
index e18cc0520..a9549b4f2 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineKeyframeViewModel.cs
@@ -31,6 +31,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
LayerPropertyKeyframe.EasingFunction,
LayerPropertyKeyframe.LayerProperty
);
+ // If possible, shift the keyframe to the right by 11 pixels
+ var desiredPosition = newKeyframe.Position + TimeSpan.FromMilliseconds(1000f / _profileEditorService.PixelsPerSecond * 11);
+ if (desiredPosition <= newKeyframe.LayerProperty.ProfileElement.TimelineLength)
+ newKeyframe.Position = desiredPosition;
+ // Otherwise if possible shift it to the left by 11 pixels
+ else
+ {
+ desiredPosition = newKeyframe.Position - TimeSpan.FromMilliseconds(1000f / _profileEditorService.PixelsPerSecond * 11);
+ if (desiredPosition > TimeSpan.Zero)
+ newKeyframe.Position = desiredPosition;
+ }
+
LayerPropertyKeyframe.LayerProperty.AddKeyframe(newKeyframe);
_profileEditorService.UpdateSelectedProfileElement();
}
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs
index cf9aad4ad..7af3c4d06 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineSegmentViewModel.cs
@@ -140,14 +140,14 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
if (Segment == SegmentViewModelType.Start)
{
// Remove keyframes that fall in this segment
- foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position < startSegmentEnd))
+ foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position <= startSegmentEnd))
baseLayerPropertyKeyframe.Remove();
SelectedProfileElement.StartSegmentLength = TimeSpan.Zero;
}
else if (Segment == SegmentViewModelType.Main)
{
// Remove keyframes that fall in this segment
- foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position > startSegmentEnd && k.Position < mainSegmentEnd))
+ foreach (var baseLayerPropertyKeyframe in keyframes.Where(k => k.Position > startSegmentEnd && k.Position <= mainSegmentEnd))
baseLayerPropertyKeyframe.Remove();
SelectedProfileElement.MainSegmentLength = TimeSpan.Zero;
}
@@ -189,7 +189,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
else if (Segment == SegmentViewModelType.End)
segmentEnd = SelectedProfileElement.TimelineLength;
- foreach (var baseLayerPropertyKeyframe in SelectedProfileElement.GetAllKeyframes().Where(k => k.Position >= segmentEnd))
+ foreach (var baseLayerPropertyKeyframe in SelectedProfileElement.GetAllKeyframes().Where(k => k.Position > segmentEnd))
baseLayerPropertyKeyframe.Position += amount;
}
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs
index dc7d0d17c..8fcf57eaf 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/LayerProperties/Timeline/TimelineViewModel.cs
@@ -7,6 +7,7 @@ using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
+using Artemis.Core.Models.Profile;
using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Abstract;
using Artemis.UI.Shared.Services.Interfaces;
using Artemis.UI.Shared.Utilities;
@@ -27,13 +28,16 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
LayerPropertyGroups = layerPropertyGroups;
SelectionRectangle = new RectangleGeometry();
+ SelectedProfileElement = layerPropertiesViewModel.SelectedProfileElement;
- _profileEditorService.SelectedProfileElement.PropertyChanged += SelectedProfileElementOnPropertyChanged;
+ SelectedProfileElement.PropertyChanged += SelectedProfileElementOnPropertyChanged;
_profileEditorService.PixelsPerSecondChanged += ProfileEditorServiceOnPixelsPerSecondChanged;
Update();
}
+ public RenderProfileElement SelectedProfileElement { get; set; }
+
public BindableCollection LayerPropertyGroups { get; }
public RectangleGeometry SelectionRectangle
@@ -42,21 +46,21 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
set => SetAndNotify(ref _selectionRectangle, value);
}
- public double StartSegmentWidth => _profileEditorService.PixelsPerSecond * _profileEditorService.SelectedProfileElement?.StartSegmentLength.TotalSeconds ?? 0;
+ public double StartSegmentWidth => _profileEditorService.PixelsPerSecond * SelectedProfileElement.StartSegmentLength.TotalSeconds;
public double StartSegmentEndPosition => StartSegmentWidth;
- public double MainSegmentWidth => _profileEditorService.PixelsPerSecond * _profileEditorService.SelectedProfileElement?.MainSegmentLength.TotalSeconds ?? 0;
+ public double MainSegmentWidth => _profileEditorService.PixelsPerSecond * SelectedProfileElement.MainSegmentLength.TotalSeconds;
public double MainSegmentEndPosition => StartSegmentWidth + MainSegmentWidth;
- public double EndSegmentWidth => _profileEditorService.PixelsPerSecond * _profileEditorService.SelectedProfileElement?.EndSegmentLength.TotalSeconds ?? 0;
+ public double EndSegmentWidth => _profileEditorService.PixelsPerSecond * SelectedProfileElement.EndSegmentLength.TotalSeconds;
public double EndSegmentEndPosition => StartSegmentWidth + MainSegmentWidth + EndSegmentWidth;
- public double TotalTimelineWidth => _profileEditorService.PixelsPerSecond * _profileEditorService.SelectedProfileElement?.TimelineLength.TotalSeconds ?? 0;
+ public double TotalTimelineWidth => _profileEditorService.PixelsPerSecond * SelectedProfileElement.TimelineLength.TotalSeconds;
- public bool StartSegmentEnabled => _profileEditorService.SelectedProfileElement?.StartSegmentLength != TimeSpan.Zero;
- public bool EndSegmentEnabled => _profileEditorService.SelectedProfileElement?.EndSegmentLength != TimeSpan.Zero;
+ public bool StartSegmentEnabled => SelectedProfileElement.StartSegmentLength != TimeSpan.Zero;
+ public bool EndSegmentEnabled => SelectedProfileElement.EndSegmentLength != TimeSpan.Zero;
public void Dispose()
{
_profileEditorService.PixelsPerSecondChanged -= ProfileEditorServiceOnPixelsPerSecondChanged;
- _profileEditorService.SelectedProfileElement.PropertyChanged -= SelectedProfileElementOnPropertyChanged;
+ SelectedProfileElement.PropertyChanged -= SelectedProfileElementOnPropertyChanged;
}
private void SelectedProfileElementOnPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -115,8 +119,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
public void KeyframeMouseDown(object sender, MouseButtonEventArgs e)
{
- if (e.LeftButton == MouseButtonState.Released)
- return;
+ // if (e.LeftButton == MouseButtonState.Released)
+ // return;
var viewModel = (sender as Ellipse)?.DataContext as TimelineKeyframeViewModel;
if (viewModel == null)
@@ -220,6 +224,18 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.Timeline
foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected))
keyframeViewModel.SaveOffsetToKeyframe(sourceKeyframeViewModel);
+ if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
+ {
+ cursorTime = _profileEditorService.SnapToTimeline(
+ cursorTime,
+ TimeSpan.FromMilliseconds(1000f / _profileEditorService.PixelsPerSecond * 5),
+ true,
+ false,
+ true,
+ sourceKeyframeViewModel.BaseLayerPropertyKeyframe
+ );
+ }
+
sourceKeyframeViewModel.UpdatePosition(cursorTime);
foreach (var keyframeViewModel in keyframeViewModels.Where(k => k.IsSelected))
diff --git a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs
index 247afd9df..4009ab0f7 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs
@@ -5,6 +5,7 @@ using System.Windows;
using Artemis.Core.Models.Profile;
using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem;
+using Artemis.UI.Shared.Events;
using Artemis.UI.Shared.Services.Interfaces;
using GongSolutions.Wpf.DragDrop;
using Stylet;
@@ -109,6 +110,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
return;
}
+ RootFolder?.Dispose();
RootFolder = _folderVmFactory.Create(folder);
_updatingTree = false;
@@ -168,9 +170,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
#region Event handlers
- private void OnProfileElementSelected(object sender, EventArgs e)
+ private void OnProfileElementSelected(object sender, RenderProfileElementEventArgs e)
{
- if (_profileEditorService.SelectedProfileElement == SelectedTreeItem?.ProfileElement)
+ if (e.RenderProfileElement == SelectedTreeItem?.ProfileElement)
return;
if (RootFolder == null)
@@ -182,13 +184,13 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree
_updatingTree = true;
RootFolder.UpdateProfileElements();
_updatingTree = false;
- if (_profileEditorService.SelectedProfileElement == null)
+ if (e.RenderProfileElement == null)
SelectedTreeItem = null;
else
{
- var vms = RootFolder.GetAllChildren();
- vms.Add(RootFolder);
- SelectedTreeItem = vms.FirstOrDefault(vm => vm.ProfileElement == _profileEditorService.SelectedProfileElement);
+ var match = RootFolder.GetAllChildren().FirstOrDefault(vm => vm.ProfileElement == e.RenderProfileElement);
+ if (match != null)
+ SelectedTreeItem = match;
}
}
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 f360b8c6f..04d32a845 100644
--- a/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs
+++ b/src/Artemis.UI/Screens/Module/ProfileEditor/ProfileTree/TreeItem/TreeItemViewModel.cs
@@ -16,10 +16,9 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{
private readonly IDialogService _dialogService;
private readonly IFolderVmFactory _folderVmFactory;
- private readonly IRenderElementService _renderElementService;
private readonly ILayerVmFactory _layerVmFactory;
private readonly IProfileEditorService _profileEditorService;
- private BindableCollection _children;
+ private readonly IRenderElementService _renderElementService;
private TreeItemViewModel _parent;
private ProfileElement _profileElement;
@@ -41,6 +40,10 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
ProfileElement = profileElement;
Children = new BindableCollection();
+
+ ProfileElement.ChildAdded += ProfileElementOnChildAdded;
+ ProfileElement.ChildRemoved += ProfileElementOnChildRemoved;
+
UpdateProfileElements();
}
@@ -56,16 +59,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
set => SetAndNotify(ref _profileElement, value);
}
- public BindableCollection Children
- {
- get => _children;
- set => SetAndNotify(ref _children, value);
- }
+ public BindableCollection Children { get; }
public abstract bool SupportsChildren { get; }
public void Dispose()
{
+ ProfileElement.ChildAdded -= ProfileElementOnChildAdded;
+ ProfileElement.ChildRemoved -= ProfileElementOnChildRemoved;
+
Dispose(true);
GC.SuppressFinalize(this);
}
@@ -94,7 +96,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
Parent.ProfileElement.RemoveChild(source.ProfileElement);
Parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order);
- Parent.UpdateProfileElements();
}
public void SetElementBehind(TreeItemViewModel source)
@@ -107,7 +108,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
Parent.ProfileElement.RemoveChild(source.ProfileElement);
Parent.ProfileElement.AddChild(source.ProfileElement, ProfileElement.Order + 1);
- Parent.UpdateProfileElements();
}
public void RemoveExistingElement(TreeItemViewModel treeItem)
@@ -118,6 +118,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
ProfileElement.RemoveChild(treeItem.ProfileElement);
Children.Remove(treeItem);
treeItem.Parent = null;
+ treeItem.Dispose();
}
public void AddExistingElement(TreeItemViewModel treeItem)
@@ -136,7 +137,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
throw new ArtemisUIException("Cannot add a folder to a profile element of type " + ProfileElement.GetType().Name);
ProfileElement.AddChild(new Folder(ProfileElement.Profile, ProfileElement, "New folder"));
- UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile();
}
@@ -146,7 +146,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
throw new ArtemisUIException("Cannot add a layer to a profile element of type " + ProfileElement.GetType().Name);
_renderElementService.CreateLayer(ProfileElement.Profile, ProfileElement, "New layer");
- UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile();
}
@@ -182,7 +181,6 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
var parent = Parent;
ProfileElement.Parent?.RemoveChild(ProfileElement);
parent.RemoveExistingElement(this);
- parent.UpdateProfileElements();
_profileEditorService.UpdateSelectedProfile();
}
@@ -236,5 +234,15 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.ProfileTree.TreeItem
{
}
}
+
+ private void ProfileElementOnChildRemoved(object sender, EventArgs e)
+ {
+ UpdateProfileElements();
+ }
+
+ private void ProfileElementOnChildAdded(object sender, EventArgs e)
+ {
+ UpdateProfileElements();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/RootViewModel.cs b/src/Artemis.UI/Screens/RootViewModel.cs
index 7beeacf04..88427dc2e 100644
--- a/src/Artemis.UI/Screens/RootViewModel.cs
+++ b/src/Artemis.UI/Screens/RootViewModel.cs
@@ -1,4 +1,5 @@
-using System.ComponentModel;
+using System;
+using System.ComponentModel;
using System.Reflection;
using System.Threading.Tasks;
using System.Timers;
@@ -21,45 +22,50 @@ namespace Artemis.UI.Screens
{
public class RootViewModel : Conductor
{
+ private readonly IRegistrationService _builtInRegistrationService;
+ private readonly ISnackbarMessageQueue _snackbarMessageQueue;
private readonly PluginSetting _colorScheme;
private readonly ICoreService _coreService;
private readonly IDebugService _debugService;
- private readonly IRegistrationService _builtInRegistrationService;
private readonly IEventAggregator _eventAggregator;
private readonly ThemeWatcher _themeWatcher;
private readonly Timer _titleUpdateTimer;
private readonly PluginSetting _windowSize;
- private bool _lostFocus;
- private bool _isSidebarVisible;
private bool _activeItemReady;
+ private bool _isSidebarVisible;
+ private bool _lostFocus;
private string _windowTitle;
+ private ISnackbarMessageQueue _mainMessageQueue;
public RootViewModel(IEventAggregator eventAggregator, SidebarViewModel sidebarViewModel, ISettingsService settingsService, ICoreService coreService,
IDebugService debugService, IRegistrationService builtInRegistrationService, ISnackbarMessageQueue snackbarMessageQueue)
{
SidebarViewModel = sidebarViewModel;
- MainMessageQueue = snackbarMessageQueue;
_eventAggregator = eventAggregator;
_coreService = coreService;
_debugService = debugService;
_builtInRegistrationService = builtInRegistrationService;
+ _snackbarMessageQueue = snackbarMessageQueue;
_titleUpdateTimer = new Timer(500);
- _titleUpdateTimer.Elapsed += (sender, args) => UpdateWindowTitle();
+
_colorScheme = settingsService.GetSetting("UI.ColorScheme", ApplicationColorScheme.Automatic);
_windowSize = settingsService.GetSetting("UI.RootWindowSize");
- _colorScheme.SettingChanged += (sender, args) => ApplyColorSchemeSetting();
+
_themeWatcher = new ThemeWatcher();
- _themeWatcher.ThemeChanged += (sender, args) => ApplyWindowsTheme(args.Theme);
ApplyColorSchemeSetting();
ActiveItem = SidebarViewModel.SelectedItem;
ActiveItemReady = true;
- SidebarViewModel.PropertyChanged += SidebarViewModelOnPropertyChanged;
}
public SidebarViewModel SidebarViewModel { get; }
- public ISnackbarMessageQueue MainMessageQueue { get; }
+
+ public ISnackbarMessageQueue MainMessageQueue
+ {
+ get => _mainMessageQueue;
+ set => SetAndNotify(ref _mainMessageQueue, value);
+ }
public bool IsSidebarVisible
{
@@ -112,6 +118,7 @@ namespace Artemis.UI.Screens
{
_eventAggregator.Publish(new MainWindowKeyEvent(sender, false, e));
}
+
public void WindowMouseDown(object sender, MouseButtonEventArgs e)
{
_eventAggregator.Publish(new MainWindowMouseEvent(sender, true, e));
@@ -176,6 +183,21 @@ namespace Artemis.UI.Screens
extensionsPaletteHelper.SetLightDark(colorScheme == ApplicationColorScheme.Dark);
}
+ private void OnTitleUpdateTimerOnElapsed(object sender, ElapsedEventArgs args)
+ {
+ UpdateWindowTitle();
+ }
+
+ private void ThemeWatcherOnThemeChanged(object sender, WindowsThemeEventArgs e)
+ {
+ ApplyWindowsTheme(e.Theme);
+ }
+
+ private void ColorSchemeOnSettingChanged(object sender, EventArgs e)
+ {
+ ApplyColorSchemeSetting();
+ }
+
#region Overrides of Screen
protected override void OnViewLoaded()
@@ -194,22 +216,54 @@ namespace Artemis.UI.Screens
protected override void OnActivate()
{
+ MainMessageQueue = _snackbarMessageQueue;
UpdateWindowTitle();
- _titleUpdateTimer.Start();
_builtInRegistrationService.RegisterBuiltInDataModelDisplays();
_builtInRegistrationService.RegisterBuiltInDataModelInputs();
_builtInRegistrationService.RegisterBuiltInPropertyEditors();
+
+ _titleUpdateTimer.Elapsed += OnTitleUpdateTimerOnElapsed;
+ _colorScheme.SettingChanged += ColorSchemeOnSettingChanged;
+ _themeWatcher.ThemeChanged += ThemeWatcherOnThemeChanged;
+ SidebarViewModel.PropertyChanged += SidebarViewModelOnPropertyChanged;
+
+ _titleUpdateTimer.Start();
}
protected override void OnDeactivate()
{
+ // Ensure no element with focus can leak, if we don't do this the root VM is retained by Window.EffectiveValues
+ // https://stackoverflow.com/a/30864434
+ Keyboard.ClearFocus();
+
+ MainMessageQueue = null;
_titleUpdateTimer.Stop();
var window = (MaterialWindow) View;
_windowSize.Value ??= new WindowSize();
_windowSize.Value.ApplyFromWindow(window);
_windowSize.Save();
+
+ _titleUpdateTimer.Elapsed -= OnTitleUpdateTimerOnElapsed;
+ _colorScheme.SettingChanged -= ColorSchemeOnSettingChanged;
+ _themeWatcher.ThemeChanged -= ThemeWatcherOnThemeChanged;
+ SidebarViewModel.PropertyChanged -= SidebarViewModelOnPropertyChanged;
+ }
+
+ protected override void OnClose()
+ {
+ SidebarViewModel.Dispose();
+
+ // Lets force the GC to run after closing the window so it is obvious to users watching task manager
+ // that closing the UI will decrease the memory footprint of the application.
+ Task.Run(async () =>
+ {
+ await Task.Delay(TimeSpan.FromSeconds(15));
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+ });
}
#endregion
diff --git a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
index 66a7d317a..f7a0e6ef4 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
@@ -3,7 +3,6 @@ using System.Linq;
using System.Timers;
using Artemis.Core.Events;
using Artemis.Core.Services.Interfaces;
-using Artemis.UI.Services;
using Artemis.UI.Shared.DataModelVisualization.Shared;
using Artemis.UI.Shared.Services;
using Stylet;
@@ -16,17 +15,16 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
private readonly IPluginService _pluginService;
private readonly Timer _updateTimer;
private bool _isModuleFilterEnabled;
- private Core.Plugins.Abstract.Module _selectedModule;
private DataModelPropertiesViewModel _mainDataModel;
- private string _propertySearch;
private List _modules;
+ private string _propertySearch;
+ private Core.Plugins.Abstract.Module _selectedModule;
public DataModelDebugViewModel(IDataModelVisualizationService dataModelVisualizationService, IPluginService pluginService)
{
_dataModelVisualizationService = dataModelVisualizationService;
_pluginService = pluginService;
_updateTimer = new Timer(500);
- _updateTimer.Elapsed += (sender, args) => MainDataModel.Update(_dataModelVisualizationService);
DisplayName = "Data model";
}
@@ -77,6 +75,7 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
{
GetDataModel();
_updateTimer.Start();
+ _updateTimer.Elapsed += OnUpdateTimerOnElapsed;
_pluginService.PluginEnabled += PluginServiceOnPluginToggled;
_pluginService.PluginDisabled += PluginServiceOnPluginToggled;
@@ -86,10 +85,16 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
protected override void OnDeactivate()
{
_updateTimer.Stop();
+ _updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
_pluginService.PluginEnabled -= PluginServiceOnPluginToggled;
_pluginService.PluginDisabled -= PluginServiceOnPluginToggled;
}
+ private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs args)
+ {
+ MainDataModel.Update(_dataModelVisualizationService);
+ }
+
private void GetDataModel()
{
MainDataModel = SelectedModule != null
diff --git a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
index 0bb7decdf..4eb80341c 100644
--- a/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
+++ b/src/Artemis.UI/Screens/Sidebar/SidebarViewModel.cs
@@ -19,7 +19,7 @@ using Stylet;
namespace Artemis.UI.Screens.Sidebar
{
- public class SidebarViewModel : PropertyChangedBase, IHandle
+ public class SidebarViewModel : PropertyChangedBase, IHandle, IDisposable
{
private readonly IKernel _kernel;
private readonly IModuleVmFactory _moduleVmFactory;
@@ -37,10 +37,10 @@ namespace Artemis.UI.Screens.Sidebar
SidebarModules = new Dictionary();
SidebarItems = new BindableCollection();
- SetupSidebar();
_pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
_pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
+ SetupSidebar();
eventAggregator.Subscribe(this);
}
@@ -64,7 +64,7 @@ namespace Artemis.UI.Screens.Sidebar
public void SetupSidebar()
{
- SidebarItems.Clear();
+ SidebarItems.Clear();
SidebarModules.Clear();
// Add all default sidebar items
@@ -194,5 +194,11 @@ namespace Artemis.UI.Screens.Sidebar
}
#endregion
+
+ public void Dispose()
+ {
+ _pluginService.PluginEnabled -= PluginServiceOnPluginEnabled;
+ _pluginService.PluginDisabled -= PluginServiceOnPluginDisabled;
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Splash/SplashViewModel.cs b/src/Artemis.UI/Screens/Splash/SplashViewModel.cs
index 2ce1dd927..d1ea31ff0 100644
--- a/src/Artemis.UI/Screens/Splash/SplashViewModel.cs
+++ b/src/Artemis.UI/Screens/Splash/SplashViewModel.cs
@@ -51,6 +51,8 @@ namespace Artemis.UI.Screens.Splash
_pluginService.CopyingBuildInPlugins -= OnPluginServiceOnCopyingBuildInPlugins;
_pluginService.PluginLoading -= OnPluginServiceOnPluginLoading;
_pluginService.PluginLoaded -= OnPluginServiceOnPluginLoaded;
+ _pluginService.PluginEnabling -= PluginServiceOnPluginEnabling;
+ _pluginService.PluginEnabled -= PluginServiceOnPluginEnabled;
base.OnClose();
}
diff --git a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigView.xaml b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigView.xaml
index 66dd4d947..7bfa6ebfe 100644
--- a/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigView.xaml
+++ b/src/Artemis.UI/Screens/SurfaceEditor/Dialogs/SurfaceDeviceConfigView.xaml
@@ -12,13 +12,23 @@
-
-
+
+
+
+
-
-
-