diff --git a/src/Artemis.Core/Extensions/SKColorExtensions.cs b/src/Artemis.Core/Extensions/SKColorExtensions.cs index 5e62f6a24..01a09837e 100644 --- a/src/Artemis.Core/Extensions/SKColorExtensions.cs +++ b/src/Artemis.Core/Extensions/SKColorExtensions.cs @@ -27,6 +27,16 @@ namespace Artemis.Core ); } + public static SKColor Sum(this SKColor a, SKColor b) + { + return new SKColor( + ClampToByte(a.Red + b.Red), + ClampToByte(a.Green + b.Green), + ClampToByte(a.Blue + b.Blue), + ClampToByte(a.Alpha + b.Alpha) + ); + } + private static byte ClampToByte(float value) { return (byte) Math.Clamp(value, 0, 255); diff --git a/src/Artemis.Core/Models/Profile/DataBindings/Converters/SKColorDataBindingConverter.cs b/src/Artemis.Core/Models/Profile/DataBindings/Converters/SKColorDataBindingConverter.cs new file mode 100644 index 000000000..d9c0a60dd --- /dev/null +++ b/src/Artemis.Core/Models/Profile/DataBindings/Converters/SKColorDataBindingConverter.cs @@ -0,0 +1,20 @@ +using SkiaSharp; + +namespace Artemis.Core +{ + /// + public class SKColorDataBindingConverter : DataBindingConverter + { + /// + public override SKColor Sum(SKColor a, SKColor b) + { + return a.Sum(b); + } + + /// + public override SKColor Interpolate(SKColor a, SKColor b, double progress) + { + return a.Interpolate(b, (float)progress); + } + } +} diff --git a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingRegistration.cs b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingRegistration.cs index d7366ca63..e1dea2169 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/DataBindingRegistration.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/DataBindingRegistration.cs @@ -40,12 +40,18 @@ namespace Artemis.Core /// null if the is not a member expression /// public MemberInfo Member { get; } - + /// /// Gets the data binding created using this registration /// public DataBinding DataBinding { get; internal set; } + /// + public IDataBinding GetDataBinding() + { + return DataBinding; + } + /// public IDataBinding CreateDataBinding() { diff --git a/src/Artemis.Core/Models/Profile/DataBindings/IDataBindingRegistration.cs b/src/Artemis.Core/Models/Profile/DataBindings/IDataBindingRegistration.cs index 2bba9c36a..d4a00e574 100644 --- a/src/Artemis.Core/Models/Profile/DataBindings/IDataBindingRegistration.cs +++ b/src/Artemis.Core/Models/Profile/DataBindings/IDataBindingRegistration.cs @@ -1,12 +1,17 @@ namespace Artemis.Core { /// - /// Represents a data binding registration + /// Represents a data binding registration /// public interface IDataBindingRegistration { /// - /// If found, creates a data binding from storage + /// Returns the data binding applied using this registration + /// + public IDataBinding GetDataBinding(); + + /// + /// If found, creates a data binding from storage /// /// IDataBinding CreateDataBinding(); diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs index 909255cb5..685972d67 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/ILayerProperty.cs @@ -13,6 +13,11 @@ namespace Artemis.Core /// public interface ILayerProperty : IStorageModel, IUpdateModel, IDisposable { + /// + /// Gets the description attribute applied to this property + /// + public PropertyDescriptionAttribute PropertyDescription { 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 01ccfc4c7..f9dcfdc58 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/LayerProperty.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using System.Reflection; using Artemis.Storage.Entities.Profile; using Newtonsoft.Json; @@ -28,9 +27,7 @@ namespace Artemis.Core _keyframes = new List>(); } - /// - /// Gets the description attribute applied to this property - /// + /// public PropertyDescriptionAttribute PropertyDescription { get; internal set; } /// @@ -49,6 +46,15 @@ namespace Artemis.Core OnUpdated(); } + /// + public void Dispose() + { + _disposed = true; + + foreach (var dataBinding in _dataBindings) + dataBinding.Dispose(); + } + /// /// Returns the type of the property /// @@ -320,6 +326,20 @@ namespace Artemis.Core /// public bool DataBindingsSupported { get; protected internal set; } = true; + /// + /// Gets whether the layer has any active data bindings + /// + public bool HasDataBinding => GetAllDataBindingRegistrations().Any(r => r.GetDataBinding() != null); + + /// + /// Gets a data binding registration by the expression used to register it + /// Note: The expression must exactly match the one used to register the data binding + /// + public DataBindingRegistration GetDataBindingRegistration(Expression> propertyExpression) + { + return GetDataBindingRegistration(propertyExpression.ToString()); + } + public DataBindingRegistration GetDataBindingRegistration(string expression) { if (_disposed) @@ -327,6 +347,7 @@ namespace Artemis.Core var match = _dataBindingRegistrations.FirstOrDefault(r => r is DataBindingRegistration registration && registration.PropertyExpression.ToString() == expression); + return (DataBindingRegistration) match; } @@ -367,6 +388,7 @@ namespace Artemis.Core var dataBinding = new DataBinding(dataBindingRegistration); _dataBindings.Add(dataBinding); + OnDataBindingEnabled(new LayerPropertyEventArgs(dataBinding.LayerProperty)); return dataBinding; } @@ -380,6 +402,10 @@ namespace Artemis.Core throw new ObjectDisposedException("LayerProperty"); _dataBindings.Remove(dataBinding); + + dataBinding.Registration.DataBinding = null; + dataBinding.Dispose(); + OnDataBindingDisabled(new LayerPropertyEventArgs(dataBinding.LayerProperty)); } private void UpdateDataBindings(double deltaTime) @@ -532,6 +558,16 @@ namespace Artemis.Core /// public event EventHandler> KeyframeRemoved; + /// + /// Occurs when a data binding has been enabled + /// + public event EventHandler> DataBindingEnabled; + + /// + /// Occurs when a data binding has been disabled + /// + public event EventHandler> DataBindingDisabled; + protected virtual void OnUpdated() { Updated?.Invoke(this, new LayerPropertyEventArgs(this)); @@ -562,15 +598,16 @@ namespace Artemis.Core KeyframeRemoved?.Invoke(this, new LayerPropertyEventArgs(this)); } - #endregion - - /// - public void Dispose() + protected virtual void OnDataBindingEnabled(LayerPropertyEventArgs e) { - _disposed = true; - - foreach (var dataBinding in _dataBindings) - dataBinding.Dispose(); + DataBindingEnabled?.Invoke(this, e); } + + protected virtual void OnDataBindingDisabled(LayerPropertyEventArgs e) + { + DataBindingDisabled?.Invoke(this, e); + } + + #endregion } } \ No newline at end of file diff --git a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs index 674086de7..a7663a789 100644 --- a/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs +++ b/src/Artemis.Core/Models/Profile/LayerProperties/Types/SKColorLayerProperty.cs @@ -7,10 +7,7 @@ namespace Artemis.Core { internal SKColorLayerProperty() { - RegisterDataBindingProperty(color => color.Alpha, new SKColorArgbDataBindingConverter(SKColorArgbDataBindingConverter.Channel.Alpha)); - RegisterDataBindingProperty(color => color.Red, new SKColorArgbDataBindingConverter(SKColorArgbDataBindingConverter.Channel.Red)); - RegisterDataBindingProperty(color => color.Green, new SKColorArgbDataBindingConverter(SKColorArgbDataBindingConverter.Channel.Green)); - RegisterDataBindingProperty(color => color.Blue, new SKColorArgbDataBindingConverter(SKColorArgbDataBindingConverter.Channel.Blue)); + RegisterDataBindingProperty(value => value, new SKColorDataBindingConverter()); } /// diff --git a/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml b/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml index 9f0133e3c..7d59a307a 100644 --- a/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml +++ b/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml @@ -3,13 +3,28 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:shared="clr-namespace:Artemis.UI.Shared" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> - + + + @@ -17,10 +32,12 @@ + Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualHeight}"> + diff --git a/src/Artemis.UI.Shared/Controls/LockableToggleButton.cs b/src/Artemis.UI.Shared/Controls/LockableToggleButton.cs new file mode 100644 index 000000000..faadc1c2a --- /dev/null +++ b/src/Artemis.UI.Shared/Controls/LockableToggleButton.cs @@ -0,0 +1,26 @@ +using System.Windows; +using System.Windows.Controls.Primitives; + +namespace Artemis.UI.Shared +{ + public class LockableToggleButton : ToggleButton + { + protected override void OnToggle() + { + if (!IsLocked) + { + base.OnToggle(); + } + } + + public bool IsLocked + { + get { return (bool)GetValue(IsLockedProperty); } + set { SetValue(IsLockedProperty, value); } + } + + // Using a DependencyProperty as the backing store for LockToggle. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsLockedProperty = + DependencyProperty.Register("IsLocked", typeof(bool), typeof(LockableToggleButton), new UIPropertyMetadata(false)); + } +} diff --git a/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs b/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs index 9d99b7515..bea49d60f 100644 --- a/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs +++ b/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs @@ -16,6 +16,8 @@ namespace Artemis.UI.Shared ProfileEditorService = profileEditorService; LayerProperty.Updated += LayerPropertyOnUpdated; LayerProperty.BaseValueChanged += LayerPropertyOnUpdated; + LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange; + LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange; UpdateInputValue(); } @@ -25,11 +27,14 @@ namespace Artemis.UI.Shared ProfileEditorService = profileEditorService; LayerProperty.Updated += LayerPropertyOnUpdated; LayerProperty.BaseValueChanged += LayerPropertyOnUpdated; + LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange; + LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange; UpdateInputValue(); } public LayerProperty LayerProperty { get; } public IProfileEditorService ProfileEditorService { get; } + internal override object InternalGuard { get; } = null; public bool InputDragging @@ -52,6 +57,8 @@ namespace Artemis.UI.Shared { LayerProperty.Updated -= LayerPropertyOnUpdated; LayerProperty.BaseValueChanged -= LayerPropertyOnUpdated; + LayerProperty.DataBindingEnabled -= LayerPropertyOnDataBindingChange; + LayerProperty.DataBindingDisabled -= LayerPropertyOnDataBindingChange; Dispose(true); GC.SuppressFinalize(this); } @@ -65,6 +72,10 @@ namespace Artemis.UI.Shared { } + protected virtual void OnDataBindingsChanged() + { + } + protected void ApplyInputValue() { // Force the validator to run @@ -123,6 +134,11 @@ namespace Artemis.UI.Shared ProfileEditorService.UpdateProfilePreview(); } + private void LayerPropertyOnDataBindingChange(object sender, LayerPropertyEventArgs e) + { + OnDataBindingsChanged(); + } + #endregion } diff --git a/src/Artemis.UI/PropertyInput/FloatPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/FloatPropertyInputView.xaml index 97c6085d6..44ce18165 100644 --- a/src/Artemis.UI/PropertyInput/FloatPropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/FloatPropertyInputView.xaml @@ -16,7 +16,8 @@ materialDesign:ValidationAssist.UsePopup="True" StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}" DragStarted="{s:Action InputDragStarted}" - DragEnded="{s:Action InputDragEnded}" /> + DragEnded="{s:Action InputDragEnded}" + IsEnabled="{Binding IsEnabled}"/> \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/FloatPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/FloatPropertyInputViewModel.cs index 4fb0372fb..eb6bbadcf 100644 --- a/src/Artemis.UI/PropertyInput/FloatPropertyInputViewModel.cs +++ b/src/Artemis.UI/PropertyInput/FloatPropertyInputViewModel.cs @@ -8,9 +8,19 @@ namespace Artemis.UI.PropertyInput { public class FloatPropertyInputViewModel : PropertyInputViewModel { + private readonly DataBindingRegistration _registration; + public FloatPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService, IModelValidator validator) : base(layerProperty, profileEditorService, validator) { + _registration = layerProperty.GetDataBindingRegistration(value => value); + } + + public bool IsEnabled => _registration.DataBinding == null; + + protected override void OnDataBindingsChanged() + { + NotifyOfPropertyChange(nameof(IsEnabled)); } } diff --git a/src/Artemis.UI/PropertyInput/IntPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/IntPropertyInputView.xaml index f280ea051..20dd7b5ab 100644 --- a/src/Artemis.UI/PropertyInput/IntPropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/IntPropertyInputView.xaml @@ -16,7 +16,8 @@ materialDesign:ValidationAssist.UsePopup="True" StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}" DragStarted="{s:Action InputDragStarted}" - DragEnded="{s:Action InputDragEnded}" /> + DragEnded="{s:Action InputDragEnded}" + IsEnabled="{Binding IsEnabled}"/> \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/IntPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/IntPropertyInputViewModel.cs index 5573db4b2..ecb3eebda 100644 --- a/src/Artemis.UI/PropertyInput/IntPropertyInputViewModel.cs +++ b/src/Artemis.UI/PropertyInput/IntPropertyInputViewModel.cs @@ -8,9 +8,19 @@ namespace Artemis.UI.PropertyInput { public class IntPropertyInputViewModel : PropertyInputViewModel { + private readonly DataBindingRegistration _registration; + public IntPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService, IModelValidator validator) : base(layerProperty, profileEditorService, validator) { + _registration = layerProperty.GetDataBindingRegistration(value => value); + } + + public bool IsEnabled => _registration.DataBinding == null; + + protected override void OnDataBindingsChanged() + { + NotifyOfPropertyChange(nameof(IsEnabled)); } } diff --git a/src/Artemis.UI/PropertyInput/SKColorPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/SKColorPropertyInputView.xaml index 18ebc86e7..90f94b311 100644 --- a/src/Artemis.UI/PropertyInput/SKColorPropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/SKColorPropertyInputView.xaml @@ -16,7 +16,8 @@ + Color="{Binding InputValue, Converter={StaticResource SKColorToColorConverter}}" + IsEnabled="{Binding IsEnabled}"/> \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/SKColorPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/SKColorPropertyInputViewModel.cs index 50d9d3264..661d6074b 100644 --- a/src/Artemis.UI/PropertyInput/SKColorPropertyInputViewModel.cs +++ b/src/Artemis.UI/PropertyInput/SKColorPropertyInputViewModel.cs @@ -7,8 +7,18 @@ namespace Artemis.UI.PropertyInput { public class SKColorPropertyInputViewModel : PropertyInputViewModel { + private readonly DataBindingRegistration _registration; + public SKColorPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService) : base(layerProperty, profileEditorService) { + _registration = layerProperty.GetDataBindingRegistration(value => value); + } + + public bool IsEnabled => _registration.DataBinding == null; + + protected override void OnDataBindingsChanged() + { + NotifyOfPropertyChange(nameof(IsEnabled)); } } } \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/SKPointPropertyInputView.xaml b/src/Artemis.UI/PropertyInput/SKPointPropertyInputView.xaml index a2661f689..7fc7753d8 100644 --- a/src/Artemis.UI/PropertyInput/SKPointPropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/SKPointPropertyInputView.xaml @@ -15,13 +15,15 @@ Value="{Binding X}" StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}" DragStarted="{s:Action InputDragStarted}" - DragEnded="{s:Action InputDragEnded}" /> + DragEnded="{s:Action InputDragEnded}" + IsEnabled="{Binding IsXEnabled}"/> , + DragEnded="{s:Action InputDragEnded}" + IsEnabled="{Binding IsYEnabled}"/> \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/SKPointPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/SKPointPropertyInputViewModel.cs index 9cd568e5e..8d7448f8b 100644 --- a/src/Artemis.UI/PropertyInput/SKPointPropertyInputViewModel.cs +++ b/src/Artemis.UI/PropertyInput/SKPointPropertyInputViewModel.cs @@ -10,9 +10,14 @@ namespace Artemis.UI.PropertyInput { public class SKPointPropertyInputViewModel : PropertyInputViewModel { + private readonly DataBindingRegistration _xRegistration; + private readonly DataBindingRegistration _yRegistration; + public SKPointPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService, IModelValidator validator) : base(layerProperty, profileEditorService, validator) { + _xRegistration = layerProperty.GetDataBindingRegistration(point => point.X); + _yRegistration = layerProperty.GetDataBindingRegistration(point => point.Y); } public float X @@ -27,11 +32,20 @@ namespace Artemis.UI.PropertyInput set => InputValue = new SKPoint(X, value); } + public bool IsXEnabled => _xRegistration.DataBinding == null; + public bool IsYEnabled => _yRegistration.DataBinding == null; + protected override void OnInputValueChanged() { NotifyOfPropertyChange(nameof(X)); NotifyOfPropertyChange(nameof(Y)); } + + protected override void OnDataBindingsChanged() + { + NotifyOfPropertyChange(nameof(IsXEnabled)); + NotifyOfPropertyChange(nameof(IsYEnabled)); + } } public class SKPointPropertyInputViewModelValidator : AbstractValidator diff --git a/src/Artemis.UI/PropertyInput/SKSizePropertyInputView.xaml b/src/Artemis.UI/PropertyInput/SKSizePropertyInputView.xaml index 245bbcdb3..03a2e1440 100644 --- a/src/Artemis.UI/PropertyInput/SKSizePropertyInputView.xaml +++ b/src/Artemis.UI/PropertyInput/SKSizePropertyInputView.xaml @@ -15,13 +15,15 @@ Value="{Binding Height}" StepSize="{Binding LayerProperty.PropertyDescription.InputStepSize}" DragStarted="{s:Action InputDragStarted}" - DragEnded="{s:Action InputDragEnded}" /> + DragEnded="{s:Action InputDragEnded}" + IsEnabled="{Binding IsHeightEnabled}"/> , + DragEnded="{s:Action InputDragEnded}" + IsEnabled="{Binding IsWidthEnabled}"/> \ No newline at end of file diff --git a/src/Artemis.UI/PropertyInput/SKSizePropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/SKSizePropertyInputViewModel.cs index 25c3bde71..ba89b56d1 100644 --- a/src/Artemis.UI/PropertyInput/SKSizePropertyInputViewModel.cs +++ b/src/Artemis.UI/PropertyInput/SKSizePropertyInputViewModel.cs @@ -4,15 +4,22 @@ using Artemis.UI.Shared; using Artemis.UI.Shared.Services; using FluentValidation; using SkiaSharp; -using Stylet; // using PropertyChanged; +using Stylet; + +// using PropertyChanged; namespace Artemis.UI.PropertyInput { public class SKSizePropertyInputViewModel : PropertyInputViewModel { + private readonly DataBindingRegistration _heightRegistration; + private readonly DataBindingRegistration _widthRegistration; + public SKSizePropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService, IModelValidator validator) : base(layerProperty, profileEditorService, validator) { + _widthRegistration = layerProperty.GetDataBindingRegistration(size => size.Width); + _heightRegistration = layerProperty.GetDataBindingRegistration(size => size.Height); } // Since SKSize is immutable we need to create properties that replace the SKSize entirely @@ -28,11 +35,20 @@ namespace Artemis.UI.PropertyInput set => InputValue = new SKSize(Width, value); } + public bool IsWidthEnabled => _widthRegistration.DataBinding == null; + public bool IsHeightEnabled => _heightRegistration.DataBinding == null; + protected override void OnInputValueChanged() { NotifyOfPropertyChange(nameof(Width)); NotifyOfPropertyChange(nameof(Height)); } + + protected override void OnDataBindingsChanged() + { + NotifyOfPropertyChange(nameof(IsWidthEnabled)); + NotifyOfPropertyChange(nameof(IsHeightEnabled)); + } } public class SKSizePropertyInputViewModelValidator : AbstractValidator diff --git a/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs index 6e9d1f6f1..6f25f8141 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/DisplayConditions/DisplayConditionsViewModel.cs @@ -56,14 +56,16 @@ namespace Artemis.UI.Screens.ProfileEditor.DisplayConditions public bool ConditionBehaviourEnabled => RenderProfileElement != null; - protected override void OnActivate() + protected override void OnInitialActivate() { _profileEditorService.ProfileElementSelected += ProfileEditorServiceOnProfileElementSelected; + base.OnInitialActivate(); } - protected override void OnDeactivate() + protected override void OnClose() { _profileEditorService.ProfileElementSelected -= ProfileEditorServiceOnProfileElementSelected; + base.OnClose(); } private void ProfileEditorServiceOnProfileElementSelected(object sender, RenderProfileElementEventArgs e) diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs index b5d6d3a09..b1e29fca2 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyGroupViewModel.cs @@ -40,6 +40,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties set => SetAndNotify(ref _isVisible, value); } + public bool IsHighlighted => false; + public bool IsExpanded { get => LayerPropertyGroup.ProfileElement.IsPropertyGroupExpanded(LayerPropertyGroup); diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs index 1e5993039..ce5c39ed7 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/LayerPropertyViewModel.cs @@ -10,6 +10,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties public class LayerPropertyViewModel : PropertyChangedBase, IDisposable { private bool _isVisible; + private bool _isHighlighted; + private bool _isExpanded; public LayerPropertyViewModel(ILayerProperty layerProperty, IPropertyVmFactory propertyVmFactory) { @@ -29,8 +31,18 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties set => SetAndNotify(ref _isVisible, value); } - public bool IsExpanded => false; - + public bool IsHighlighted + { + get => _isHighlighted; + set => SetAndNotify(ref _isHighlighted, value); + } + + public bool IsExpanded + { + get => _isExpanded; + set => SetAndNotify(ref _isExpanded, value); + } + public void Dispose() { TreePropertyViewModel?.Dispose(); diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyView.xaml index ff231f5e0..dc3ff8719 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyView.xaml @@ -5,6 +5,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:s="https://github.com/canton7/Stylet" + xmlns:shared="clr-namespace:Artemis.UI.Shared;assembly=Artemis.UI.Shared" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> @@ -43,15 +44,17 @@ - + IsChecked="{Binding HasDataBinding, Mode=OneWay}" + Click="{s:Action ActivateDataBindingViewModel}"> - + \ 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 bfc7950b0..ffb12a669 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreePropertyViewModel.cs @@ -22,10 +22,11 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree PropertyInputViewModel = _profileEditorService.CreatePropertyInputViewModel(LayerProperty); _profileEditorService.SelectedDataBindingChanged += ProfileEditorServiceOnSelectedDataBindingChanged; LayerProperty.VisibilityChanged += LayerPropertyOnVisibilityChanged; - + LayerProperty.DataBindingEnabled += LayerPropertyOnDataBindingChange; + LayerProperty.DataBindingDisabled += LayerPropertyOnDataBindingChange; LayerPropertyViewModel.IsVisible = !LayerProperty.IsHidden; } - + public LayerProperty LayerProperty { get; } public LayerPropertyViewModel LayerPropertyViewModel { get; } @@ -35,6 +36,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree set => SetAndNotify(ref _propertyInputViewModel, value); } + public bool HasDataBinding => LayerProperty.HasDataBinding; + public bool HasPropertyInputViewModel => PropertyInputViewModel != null; public bool KeyframesEnabled @@ -43,10 +46,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree set => ApplyKeyframesEnabled(value); } - public bool DataBindingsOpen + public void ActivateDataBindingViewModel() { - get => _profileEditorService.SelectedDataBinding == LayerProperty; - set => _profileEditorService.ChangeSelectedDataBinding(value ? LayerProperty : null); + if (_profileEditorService.SelectedDataBinding == LayerProperty) + _profileEditorService.ChangeSelectedDataBinding(null); + else + _profileEditorService.ChangeSelectedDataBinding(LayerProperty); } #region IDisposable @@ -56,6 +61,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree _propertyInputViewModel?.Dispose(); _profileEditorService.SelectedDataBindingChanged -= ProfileEditorServiceOnSelectedDataBindingChanged; LayerProperty.VisibilityChanged -= LayerPropertyOnVisibilityChanged; + LayerProperty.DataBindingEnabled -= LayerPropertyOnDataBindingChange; + LayerProperty.DataBindingDisabled -= LayerPropertyOnDataBindingChange; } #endregion @@ -85,7 +92,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree private void ProfileEditorServiceOnSelectedDataBindingChanged(object sender, EventArgs e) { - NotifyOfPropertyChange(nameof(DataBindingsOpen)); + LayerPropertyViewModel.IsHighlighted = _profileEditorService.SelectedDataBinding == LayerProperty; } private void LayerPropertyOnVisibilityChanged(object? sender, LayerPropertyEventArgs e) @@ -93,12 +100,17 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.Tree LayerPropertyViewModel.IsVisible = !LayerProperty.IsHidden; } + private void LayerPropertyOnDataBindingChange(object? sender, LayerPropertyEventArgs e) + { + NotifyOfPropertyChange(nameof(HasDataBinding)); + } + #endregion } - public interface ITreePropertyViewModel : IScreen, INotifyPropertyChanged, IDisposable + public interface ITreePropertyViewModel : IScreen, IDisposable { bool HasPropertyInputViewModel { get; } - bool DataBindingsOpen { get; set; } + bool HasDataBinding { get; } } } \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeView.xaml b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeView.xaml index 006b38186..1d2d9aaee 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/LayerProperties/Tree/TreeView.xaml @@ -96,7 +96,7 @@ - + diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs index f76a54e97..5f82e8b6a 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileEditorViewModel.cs @@ -234,7 +234,7 @@ namespace Artemis.UI.Screens.ProfileEditor _snackbarMessageQueue.Enqueue("Redid profile update", "UNDO", Undo); } - protected override void OnActivate() + protected override void OnInitialActivate() { LoadWorkspaceSettings(); Module.IsProfileUpdatingDisabled = true; @@ -246,10 +246,10 @@ namespace Artemis.UI.Screens.ProfileEditor SelectedProfile = Profiles.FirstOrDefault(d => d.Id == Module.ActiveProfile.EntityId); Task.Run(async () => { await _moduleService.SetActiveModuleOverride(Module); }); - base.OnActivate(); + base.OnInitialActivate(); } - protected override void OnDeactivate() + protected override void OnClose() { SaveWorkspaceSettings(); Module.IsProfileUpdatingDisabled = false; @@ -257,7 +257,7 @@ namespace Artemis.UI.Screens.ProfileEditor _profileEditorService.ChangeSelectedProfile(null); Task.Run(async () => { await _moduleService.SetActiveModuleOverride(null); }); - base.OnDeactivate(); + base.OnClose(); } private void RemoveProfile(ProfileDescriptor profileDescriptor) diff --git a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs index 1502ac21e..76ef61fdd 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/ProfileTree/ProfileTreeViewModel.cs @@ -96,16 +96,16 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree ActiveItem?.AddLayer(); } - protected override void OnActivate() + protected override void OnInitialActivate() { Subscribe(); - base.OnActivate(); + base.OnInitialActivate(); } - protected override void OnDeactivate() + protected override void OnClose() { Unsubscribe(); - base.OnDeactivate(); + base.OnClose(); } private void CreateRootFolderViewModel() diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileViewModel.cs index 32bc7f957..b1ec9cc9d 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/ProfileViewModel.cs @@ -173,7 +173,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization .ToList(); } - protected override void OnActivate() + protected override void OnInitialActivate() { ApplyActiveProfile(); @@ -186,10 +186,10 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization _profileEditorService.ProfileElementSelected += OnProfileElementSelected; _profileEditorService.SelectedProfileElementUpdated += OnSelectedProfileElementUpdated; - base.OnActivate(); + base.OnInitialActivate(); } - protected override void OnDeactivate() + protected override void OnClose() { HighlightSelectedLayer.SettingChanged -= HighlightSelectedLayerOnSettingChanged; _surfaceService.ActiveSurfaceConfigurationSelected -= OnActiveSurfaceConfigurationSelected; @@ -206,7 +206,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization canvasViewModel.Dispose(); CanvasViewModels.Clear(); - base.OnDeactivate(); + base.OnClose(); } private void OnActiveSurfaceConfigurationSelected(object sender, SurfaceConfigurationEventArgs e)