From d0fbd6359228c7033473d2f70bb655e7ac35e613 Mon Sep 17 00:00:00 2001 From: Robert Date: Fri, 13 Mar 2020 23:45:25 +0100 Subject: [PATCH] Gradient editor - WIP commit --- src/Artemis.Core/Artemis.Core.csproj | 2 +- .../Models/Profile/ColorGradient.cs | 24 ++-- src/Artemis.Storage/Artemis.Storage.csproj | 2 +- .../Artemis.UI.Shared.csproj | 1 + .../ColorGradientToGradientStopsConverter.cs | 8 +- src/Artemis.UI.Shared/GradientPicker.xaml | 2 +- src/Artemis.UI.Shared/GradientPicker.xaml.cs | 46 +++---- .../Ninject/Factories/IVMFactory.cs | 14 +++ .../Ninject/SharedUIModule.cs | 37 ++++++ .../Screens/GradientEditor/ColorStopView.xaml | 34 +++++ .../GradientEditor/ColorStopViewModel.cs | 80 ++++++++++++ .../GradientEditor/GradientEditor.xaml.cs | 70 ----------- .../GradientEditor/GradientEditorColor.xaml | 32 ----- .../GradientEditorColor.xaml.cs | 118 ------------------ ...entEditor.xaml => GradientEditorView.xaml} | 69 +++++----- .../GradientEditor/GradientEditorViewModel.cs | 46 +++++++ .../Services/GradientPickerService.cs | 20 ++- .../Interfaces/IGradientPickerService.cs | 6 +- src/Artemis.UI/Bootstrapper.cs | 5 +- src/Artemis.UI/Ninject/UiModule.cs | 11 -- .../ColorBrush.cs | 10 +- 21 files changed, 315 insertions(+), 322 deletions(-) create mode 100644 src/Artemis.UI.Shared/Ninject/Factories/IVMFactory.cs create mode 100644 src/Artemis.UI.Shared/Ninject/SharedUIModule.cs create mode 100644 src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopView.xaml create mode 100644 src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs delete mode 100644 src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditor.xaml.cs delete mode 100644 src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorColor.xaml delete mode 100644 src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorColor.xaml.cs rename src/Artemis.UI.Shared/Screens/GradientEditor/{GradientEditor.xaml => GradientEditorView.xaml} (60%) create mode 100644 src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorViewModel.cs diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 591455a61..909fe3dc8 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -40,7 +40,7 @@ - + diff --git a/src/Artemis.Core/Models/Profile/ColorGradient.cs b/src/Artemis.Core/Models/Profile/ColorGradient.cs index 921f7caf6..874c6a11e 100644 --- a/src/Artemis.Core/Models/Profile/ColorGradient.cs +++ b/src/Artemis.Core/Models/Profile/ColorGradient.cs @@ -12,20 +12,20 @@ namespace Artemis.Core.Models.Profile { public ColorGradient() { - Colors = new BindableCollection(); + Stops = new BindableCollection(); } - public BindableCollection Colors { get; } + public BindableCollection Stops { get; } public float Rotation { get; set; } public SKColor[] GetColorsArray() { - return Colors.OrderBy(c => c.Position).Select(c => c.Color).ToArray(); + return Stops.OrderBy(c => c.Position).Select(c => c.Color).ToArray(); } - public float[] GetColorPositionsArray() + public float[] GetPositionsArray() { - return Colors.OrderBy(c => c.Position).Select(c => c.Position).ToArray(); + return Stops.OrderBy(c => c.Position).Select(c => c.Position).ToArray(); } #region PropertyChanged @@ -42,18 +42,18 @@ namespace Artemis.Core.Models.Profile public void OnColorValuesUpdated() { - OnPropertyChanged(nameof(Colors)); + OnPropertyChanged(nameof(Stops)); } public SKColor GetColor(float position) { - var point = Colors.SingleOrDefault(f => f.Position == position); + var point = Stops.SingleOrDefault(f => f.Position == position); if (point != null) return point.Color; - var before = Colors.First(w => w.Position == Colors.Min(m => m.Position)); - var after = Colors.First(w => w.Position == Colors.Max(m => m.Position)); + var before = Stops.First(w => w.Position == Stops.Min(m => m.Position)); + var after = Stops.First(w => w.Position == Stops.Max(m => m.Position)); - foreach (var gs in Colors) + foreach (var gs in Stops) { if (gs.Position < position && gs.Position > before.Position) before = gs; @@ -71,9 +71,9 @@ namespace Artemis.Core.Models.Profile } } - public class ColorGradientColor : INotifyPropertyChanged + public class ColorGradientStop : INotifyPropertyChanged { - public ColorGradientColor(SKColor color, float position) + public ColorGradientStop(SKColor color, float position) { Color = color; Position = position; diff --git a/src/Artemis.Storage/Artemis.Storage.csproj b/src/Artemis.Storage/Artemis.Storage.csproj index 461e90836..0247c7075 100644 --- a/src/Artemis.Storage/Artemis.Storage.csproj +++ b/src/Artemis.Storage/Artemis.Storage.csproj @@ -5,6 +5,6 @@ 7 - + \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj index 100d13b6a..60cb67ff1 100644 --- a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj +++ b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj @@ -24,6 +24,7 @@ + diff --git a/src/Artemis.UI.Shared/Converters/ColorGradientToGradientStopsConverter.cs b/src/Artemis.UI.Shared/Converters/ColorGradientToGradientStopsConverter.cs index 22e225613..a5c82a4cb 100644 --- a/src/Artemis.UI.Shared/Converters/ColorGradientToGradientStopsConverter.cs +++ b/src/Artemis.UI.Shared/Converters/ColorGradientToGradientStopsConverter.cs @@ -14,12 +14,12 @@ namespace Artemis.UI.Shared.Converters /// Converts into a /// . /// - [ValueConversion(typeof(BindableCollection), typeof(GradientStopCollection))] + [ValueConversion(typeof(BindableCollection), typeof(GradientStopCollection))] public class ColorGradientToGradientStopsConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - var colorGradients = (BindableCollection) value; + var colorGradients = (BindableCollection) value; var collection = new GradientStopCollection(); if (colorGradients == null) return collection; @@ -32,12 +32,12 @@ namespace Artemis.UI.Shared.Converters public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var collection = (GradientStopCollection) value; - var colorGradients = new BindableCollection(); + var colorGradients = new BindableCollection(); if (collection == null) return colorGradients; foreach (var c in collection.OrderBy(s => s.Offset)) - colorGradients.Add(new ColorGradientColor(new SKColor(c.Color.R, c.Color.G, c.Color.B, c.Color.A), (float) c.Offset)); + colorGradients.Add(new ColorGradientStop(new SKColor(c.Color.R, c.Color.G, c.Color.B, c.Color.A), (float) c.Offset)); return colorGradients; } } diff --git a/src/Artemis.UI.Shared/GradientPicker.xaml b/src/Artemis.UI.Shared/GradientPicker.xaml index a52591756..a2de5e8bd 100644 --- a/src/Artemis.UI.Shared/GradientPicker.xaml +++ b/src/Artemis.UI.Shared/GradientPicker.xaml @@ -43,7 +43,7 @@ + GradientStops="{Binding ColorGradient.Stops, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource ColorGradientToGradientStopsConverter}}" /> diff --git a/src/Artemis.UI.Shared/GradientPicker.xaml.cs b/src/Artemis.UI.Shared/GradientPicker.xaml.cs index c735e1f90..e41df9eb5 100644 --- a/src/Artemis.UI.Shared/GradientPicker.xaml.cs +++ b/src/Artemis.UI.Shared/GradientPicker.xaml.cs @@ -6,7 +6,6 @@ using System.Windows.Controls; using System.Windows.Input; using Artemis.Core.Models.Profile; using Artemis.UI.Shared.Annotations; -using Artemis.UI.Shared.Screens.GradientEditor; using Artemis.UI.Shared.Services.Interfaces; namespace Artemis.UI.Shared @@ -16,8 +15,16 @@ namespace Artemis.UI.Shared /// public partial class GradientPicker : UserControl, INotifyPropertyChanged { + private static IGradientPickerService _gradientPickerService; + private bool _inCallback; + + public GradientPicker() + { + InitializeComponent(); + } + /// - /// Used by the gradient picker to load saved gradients, do not touch or it'll just throw an exception + /// Used by the gradient picker to load saved gradients, do not touch or it'll just throw an exception /// public static IGradientPickerService GradientPickerService { @@ -30,25 +37,9 @@ namespace Artemis.UI.Shared } } - public static readonly DependencyProperty ColorGradientProperty = DependencyProperty.Register(nameof(ColorGradient), typeof(ColorGradient), typeof(GradientPicker), - new FrameworkPropertyMetadata(default(ColorGradient), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ColorGradientPropertyChangedCallback)); - - public static readonly RoutedEvent ColorGradientChangedEvent = - EventManager.RegisterRoutedEvent( - nameof(ColorGradient), - RoutingStrategy.Bubble, - typeof(RoutedPropertyChangedEventHandler), - typeof(GradientPicker)); - - private static IGradientPickerService _gradientPickerService; - - private bool _inCallback; - - public GradientPicker() - { - InitializeComponent(); - } - + /// + /// Gets or sets the currently selected color gradient + /// public ColorGradient ColorGradient { get => (ColorGradient) GetValue(ColorGradientProperty); @@ -76,8 +67,17 @@ namespace Artemis.UI.Shared private void UIElement_OnMouseUp(object sender, MouseButtonEventArgs e) { - var gradientEditor = new GradientEditor(ColorGradient); - gradientEditor.ShowDialog(); + GradientPickerService.ShowGradientPicker(ColorGradient); } + + #region Static WPF fields + + public static readonly DependencyProperty ColorGradientProperty = DependencyProperty.Register(nameof(ColorGradient), typeof(ColorGradient), typeof(GradientPicker), + new FrameworkPropertyMetadata(default(ColorGradient), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ColorGradientPropertyChangedCallback)); + + public static readonly RoutedEvent ColorGradientChangedEvent = + EventManager.RegisterRoutedEvent(nameof(ColorGradient), RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler), typeof(GradientPicker)); + + #endregion } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI.Shared/Ninject/Factories/IVMFactory.cs new file mode 100644 index 000000000..026791701 --- /dev/null +++ b/src/Artemis.UI.Shared/Ninject/Factories/IVMFactory.cs @@ -0,0 +1,14 @@ +using Artemis.Core.Models.Profile; +using Artemis.UI.Shared.Screens.GradientEditor; + +namespace Artemis.UI.Shared.Ninject.Factories +{ + public interface IVmFactory + { + } + + public interface IGradientEditorVmFactory : IVmFactory + { + GradientEditorViewModel Create(ColorGradient colorGradient); + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Ninject/SharedUIModule.cs b/src/Artemis.UI.Shared/Ninject/SharedUIModule.cs new file mode 100644 index 000000000..82e2d5cfa --- /dev/null +++ b/src/Artemis.UI.Shared/Ninject/SharedUIModule.cs @@ -0,0 +1,37 @@ +using System; +using Artemis.UI.Shared.Ninject.Factories; +using Artemis.UI.Shared.Services.Interfaces; +using Ninject.Extensions.Conventions; +using Ninject.Modules; + +namespace Artemis.UI.Shared.Ninject +{ + // ReSharper disable once InconsistentNaming + public class SharedUIModule : NinjectModule + { + public override void Load() + { + if (Kernel == null) + throw new ArgumentNullException("Kernel shouldn't be null here."); + + // Bind UI factories + Kernel.Bind(x => + { + x.FromAssemblyContaining() + .SelectAllInterfaces() + .InheritedFrom() + .BindToFactory(); + }); + + // Bind all shared UI services as singletons + Kernel.Bind(x => + { + x.FromAssemblyContaining() + .SelectAllClasses() + .InheritedFrom() + .BindAllInterfaces() + .Configure(c => c.InSingletonScope()); + }); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopView.xaml b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopView.xaml new file mode 100644 index 000000000..cb2854546 --- /dev/null +++ b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopView.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs new file mode 100644 index 000000000..cafdfca8d --- /dev/null +++ b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs @@ -0,0 +1,80 @@ +using System; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using Artemis.Core.Models.Profile; +using PropertyChanged; +using SkiaSharp; +using Stylet; + +namespace Artemis.UI.Shared.Screens.GradientEditor +{ + public class ColorStopViewModel : PropertyChangedBase + { + private readonly GradientEditorViewModel _gradientEditorViewModel; + + public ColorStopViewModel(GradientEditorViewModel gradientEditorViewModel) + { + _gradientEditorViewModel = gradientEditorViewModel; + } + + public ColorGradientStop ColorStop { get; set; } + public double Offset => ColorStop.Position * _gradientEditorViewModel.PreviewWidth; + public SKColor Color => ColorStop.Color; + + #region Movement + + private double _mouseDownOffset; + private DateTime _mouseDownTime; + + public void StopMouseDown(object sender, MouseButtonEventArgs e) + { + var position = GetPositionInPreview(sender, e); + ((IInputElement) sender).CaptureMouse(); + _mouseDownOffset = Offset - position.X; + _mouseDownTime = DateTime.Now; + } + + public void StopMouseUp(object sender, MouseButtonEventArgs e) + { + // On regular click, select this color stop + if (DateTime.Now - _mouseDownTime <= TimeSpan.FromMilliseconds(250)) + { + } + + ((IInputElement) sender).ReleaseMouseCapture(); + e.Handled = true; + } + + public void StopMouseMove(object sender, MouseEventArgs e) + { + if (!((IInputElement) sender).IsMouseCaptured) + return; + + var position = GetPositionInPreview(sender, e); + // Scale down with a precision of 3 decimals + var newPosition = Math.Round((position.X + _mouseDownOffset) / _gradientEditorViewModel.PreviewWidth, 3, MidpointRounding.AwayFromZero); + // Limit from 0.0 to 1.0 + newPosition = Math.Min(1, Math.Max(0, newPosition)); + + ColorStop.Position = (float) newPosition; + NotifyOfPropertyChange(() => Offset); + NotifyOfPropertyChange(() => Color); + } + + private Point GetPositionInPreview(object sender, MouseEventArgs e) + { + var parent = VisualTreeHelper.GetParent((DependencyObject) sender); + return e.GetPosition((IInputElement) parent); + } + + #endregion + + public void Update(ColorGradientStop colorStop) + { + ColorStop = colorStop; + NotifyOfPropertyChange(() => Offset); + NotifyOfPropertyChange(() => Color); + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditor.xaml.cs b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditor.xaml.cs deleted file mode 100644 index ac1ce5a91..000000000 --- a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditor.xaml.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.CompilerServices; -using System.Windows; -using Artemis.Core.Models.Profile; -using Artemis.UI.Shared.Annotations; -using MaterialDesignExtensions.Controls; - -namespace Artemis.UI.Shared.Screens.GradientEditor -{ - /// - /// Interaction logic for GradientEditor.xaml - /// - public partial class GradientEditor : MaterialWindow, INotifyPropertyChanged - { - public static readonly DependencyProperty ColorGradientProperty = DependencyProperty.Register(nameof(ColorGradient), typeof(ColorGradient), typeof(GradientEditor), - new FrameworkPropertyMetadata(default(ColorGradient), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ColorGradientPropertyChangedCallback)); - - public static readonly RoutedEvent ColorGradientChangedEvent = - EventManager.RegisterRoutedEvent( - nameof(ColorGradient), - RoutingStrategy.Bubble, - typeof(RoutedPropertyChangedEventHandler), - typeof(GradientEditor)); - - private bool _inCallback; - - public GradientEditor(ColorGradient colorGradient) - { - DataContext = this; - - InitializeComponent(); - ColorGradient = colorGradient; - } - - public ColorGradient ColorGradient - { - get => (ColorGradient) GetValue(ColorGradientProperty); - set => SetValue(ColorGradientProperty, value); - } - - public event PropertyChangedEventHandler PropertyChanged; - - [NotifyPropertyChangedInvocator] - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - private static void ColorGradientPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var editor = (GradientEditor) d; - if (editor._inCallback) - return; - - editor._inCallback = true; - editor.OnPropertyChanged(nameof(ColorGradient)); - editor._inCallback = false; - } - - private void Rectangle_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) - { - var position = e.GetPosition((IInputElement) sender); - // Position ranges from 0.0 to 1.0 - var newPosition = (float) Math.Min(1, Math.Max(0, Math.Round((position.X) / 435.0, 3, MidpointRounding.AwayFromZero))); - - ColorGradient.Colors.Add(new ColorGradientColor(ColorGradient.GetColor(newPosition), newPosition)); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorColor.xaml b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorColor.xaml deleted file mode 100644 index 4b6d9403d..000000000 --- a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorColor.xaml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorColor.xaml.cs b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorColor.xaml.cs deleted file mode 100644 index ec7031e29..000000000 --- a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorColor.xaml.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using Artemis.Core.Models.Profile; -using Artemis.UI.Shared.Annotations; -using Artemis.UI.Shared.Utilities; - -namespace Artemis.UI.Shared.Screens.GradientEditor -{ - /// - /// Interaction logic for GradientEditorColor.xaml - /// - public partial class GradientEditorColor : UserControl, INotifyPropertyChanged - { - private const double CanvasWidth = 435.0; - - public static readonly DependencyProperty ColorGradientColorProperty = DependencyProperty.Register(nameof(GradientColor), typeof(ColorGradientColor), typeof(GradientEditorColor), - new FrameworkPropertyMetadata(default(ColorGradientColor), ColorGradientColorPropertyChangedCallback)); - - public static readonly DependencyProperty ColorGradientProperty = DependencyProperty.Register(nameof(ColorGradient), typeof(ColorGradient), typeof(GradientEditorColor), - new FrameworkPropertyMetadata(default(ColorGradient))); - - private readonly Canvas _previewCanvas; - - private bool _inCallback; - private double _mouseDownOffset; - private DateTime _mouseDownTime; - - public GradientEditorColor() - { - InitializeComponent(); - - var window = Application.Current.Windows.OfType().FirstOrDefault(); - _previewCanvas = UIUtilities.FindChild(window, "PreviewCanvas"); - } - - public ColorGradient ColorGradient - { - get => (ColorGradient) GetValue(ColorGradientProperty); - set => SetValue(ColorGradientProperty, value); - } - - public ColorGradientColor GradientColor - { - get => (ColorGradientColor) GetValue(ColorGradientColorProperty); - set => SetValue(ColorGradientColorProperty, value); - } - - public event PropertyChangedEventHandler PropertyChanged; - - [NotifyPropertyChangedInvocator] - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - private static void ColorGradientColorPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var self = (GradientEditorColor) d; - if (self._inCallback) - return; - - self._inCallback = true; - - - self.OnPropertyChanged(nameof(GradientColor)); - self.Update(); - self._inCallback = false; - } - - private void Update() - { - ColorStop.SetValue(Canvas.LeftProperty, CanvasWidth * GradientColor.Position); - ColorStop.Fill = new SolidColorBrush(Color.FromArgb( - GradientColor.Color.Alpha, - GradientColor.Color.Red, - GradientColor.Color.Green, - GradientColor.Color.Blue - )); - } - - private void ColorStop_MouseDown(object sender, MouseButtonEventArgs e) - { - ((IInputElement) sender).CaptureMouse(); - _mouseDownOffset = (double) ColorStop.GetValue(Canvas.LeftProperty) - e.GetPosition(_previewCanvas).X; - _mouseDownTime = DateTime.Now; - } - - private void ColorStop_MouseUp(object sender, MouseButtonEventArgs e) - { - // On regular click, select this color stop - if (DateTime.Now - _mouseDownTime <= TimeSpan.FromMilliseconds(250)) - { - } - - ((IInputElement) sender).ReleaseMouseCapture(); - e.Handled = true; - } - - private void ColorStop_MouseMove(object sender, MouseEventArgs e) - { - if (!((IInputElement) sender).IsMouseCaptured) - return; - - var position = e.GetPosition(_previewCanvas); - // Position ranges from 0.0 to 1.0 - var newPosition = Math.Min(1, Math.Max(0, Math.Round((position.X + _mouseDownOffset) / CanvasWidth, 3, MidpointRounding.AwayFromZero))); - GradientColor.Position = (float) newPosition; - ColorGradient.OnColorValuesUpdated(); - Update(); - } - } -} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditor.xaml b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorView.xaml similarity index 60% rename from src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditor.xaml rename to src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorView.xaml index 4a9244a62..847602f85 100644 --- a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditor.xaml +++ b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorView.xaml @@ -1,14 +1,14 @@ - + d:DesignWidth="800" + d:DataContext="{d:DesignInstance local:GradientEditorViewModel}"> @@ -41,43 +42,31 @@ Gradient - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - Stops + + + + + + + + + + + + + + + + + Selected stop diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorViewModel.cs b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorViewModel.cs new file mode 100644 index 000000000..ac9a0bf60 --- /dev/null +++ b/src/Artemis.UI.Shared/Screens/GradientEditor/GradientEditorViewModel.cs @@ -0,0 +1,46 @@ +using System.ComponentModel; +using System.Linq; +using Artemis.Core.Models.Profile; +using Stylet; + +namespace Artemis.UI.Shared.Screens.GradientEditor +{ + public class GradientEditorViewModel : Screen + { + public GradientEditorViewModel(ColorGradient colorGradient) + { + ColorGradient = colorGradient; + ColorStopViewModels = new BindableCollection(); + + ColorGradient.PropertyChanged += ColorGradientOnPropertyChanged; + UpdateColorStopViewModels(); + } + + public BindableCollection ColorStopViewModels { get; set; } + + public ColorGradient ColorGradient { get; } + public double PreviewWidth => 440; + + private void ColorGradientOnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == nameof(ColorGradient.Stops)) + UpdateColorStopViewModels(); + } + + private void UpdateColorStopViewModels() + { + while (ColorGradient.Stops.Count > ColorStopViewModels.Count) + ColorStopViewModels.Add(new ColorStopViewModel(this)); + while (ColorGradient.Stops.Count < ColorStopViewModels.Count) + ColorStopViewModels.RemoveAt(0); + + var index = 0; + foreach (var colorStop in ColorGradient.Stops.OrderBy(s => s.Position)) + { + var viewModel = ColorStopViewModels[index]; + viewModel.Update(colorStop); + index++; + } + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Services/GradientPickerService.cs b/src/Artemis.UI.Shared/Services/GradientPickerService.cs index db7b877ba..1c6e22e0c 100644 --- a/src/Artemis.UI.Shared/Services/GradientPickerService.cs +++ b/src/Artemis.UI.Shared/Services/GradientPickerService.cs @@ -1,8 +1,26 @@ -using Artemis.UI.Shared.Services.Interfaces; +using Artemis.Core.Models.Profile; +using Artemis.UI.Shared.Ninject.Factories; +using Artemis.UI.Shared.Screens.GradientEditor; +using Artemis.UI.Shared.Services.Interfaces; +using Ninject; +using Stylet; namespace Artemis.UI.Shared.Services { public class GradientPickerService : IGradientPickerService { + private readonly IGradientEditorVmFactory _gradientEditorVmFactory; + private readonly IWindowManager _windowManager; + + public GradientPickerService(IGradientEditorVmFactory gradientEditorVmFactory, IWindowManager windowManager) + { + _gradientEditorVmFactory = gradientEditorVmFactory; + _windowManager = windowManager; + } + + public void ShowGradientPicker(ColorGradient colorGradient) + { + _windowManager.ShowDialog(_gradientEditorVmFactory.Create(colorGradient)); + } } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IGradientPickerService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IGradientPickerService.cs index f1d0cc43d..cd750dce4 100644 --- a/src/Artemis.UI.Shared/Services/Interfaces/IGradientPickerService.cs +++ b/src/Artemis.UI.Shared/Services/Interfaces/IGradientPickerService.cs @@ -1,7 +1,9 @@ -namespace Artemis.UI.Shared.Services.Interfaces +using Artemis.Core.Models.Profile; + +namespace Artemis.UI.Shared.Services.Interfaces { public interface IGradientPickerService : IArtemisSharedUIService { - + void ShowGradientPicker(ColorGradient colorGradient); } } \ No newline at end of file diff --git a/src/Artemis.UI/Bootstrapper.cs b/src/Artemis.UI/Bootstrapper.cs index 6f10c09dd..77b25d542 100644 --- a/src/Artemis.UI/Bootstrapper.cs +++ b/src/Artemis.UI/Bootstrapper.cs @@ -9,6 +9,7 @@ using Artemis.Core.Services.Interfaces; using Artemis.UI.Ninject; using Artemis.UI.Screens; using Artemis.UI.Screens.Splash; +using Artemis.UI.Shared.Ninject; using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Stylet; using Ninject; @@ -76,10 +77,12 @@ namespace Artemis.UI { kernel.Settings.InjectNonPublic = true; - // Load this assembly's module + // Load the UI modules kernel.Load(); + kernel.Load(); // Load the core assembly's module kernel.Load(); + base.ConfigureIoC(kernel); } diff --git a/src/Artemis.UI/Ninject/UiModule.cs b/src/Artemis.UI/Ninject/UiModule.cs index 179702e38..6f9550f7b 100644 --- a/src/Artemis.UI/Ninject/UiModule.cs +++ b/src/Artemis.UI/Ninject/UiModule.cs @@ -5,7 +5,6 @@ using Artemis.UI.Screens.Module.ProfileEditor; using Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.PropertyInput; using Artemis.UI.Services.Interfaces; using Artemis.UI.Shared.Services.Dialog; -using Artemis.UI.Shared.Services.Interfaces; using Artemis.UI.Stylet; using FluentValidation; using Ninject.Extensions.Conventions; @@ -87,16 +86,6 @@ namespace Artemis.UI.Ninject .InheritedFrom() .BindAllInterfaces(); }); - - // Bind all shared UI services as singletons - Kernel.Bind(x => - { - x.FromAssemblyContaining() - .SelectAllClasses() - .InheritedFrom() - .BindAllInterfaces() - .Configure(c => c.InSingletonScope()); - }); } } } \ No newline at end of file diff --git a/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs b/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs index 76ada6623..ba35d170a 100644 --- a/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs +++ b/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrush.cs @@ -27,12 +27,12 @@ namespace Artemis.Plugins.LayerBrushes.Color GradientTypeProperty.ValueChanged += (sender, args) => CreateShader(_shaderBounds); GradientProperty.ValueChanged += (sender, args) => CreateShader(_shaderBounds); GradientProperty.Value.PropertyChanged += (sender, args) => CreateShader(_shaderBounds); - if (!GradientProperty.Value.Colors.Any()) + if (!GradientProperty.Value.Stops.Any()) { for (var i = 0; i < 9; i++) { var color = i != 8 ? SKColor.FromHsv(i * 32, 100, 100) : SKColor.FromHsv(0, 100, 100); - GradientProperty.Value.Colors.Add(new ColorGradientColor(color, 0.125f * i)); + GradientProperty.Value.Stops.Add(new ColorGradientStop(color, 0.125f * i)); } } } @@ -74,17 +74,17 @@ namespace Artemis.Plugins.LayerBrushes.Color case GradientType.LinearGradient: shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(pathBounds.Width, 0), GradientProperty.Value.GetColorsArray(), - GradientProperty.Value.GetColorPositionsArray(), SKShaderTileMode.Repeat); + GradientProperty.Value.GetPositionsArray(), SKShaderTileMode.Repeat); break; case GradientType.RadialGradient: shader = SKShader.CreateRadialGradient(center, Math.Min(pathBounds.Width, pathBounds.Height), GradientProperty.Value.GetColorsArray(), - GradientProperty.Value.GetColorPositionsArray(), SKShaderTileMode.Repeat); + GradientProperty.Value.GetPositionsArray(), SKShaderTileMode.Repeat); break; case GradientType.SweepGradient: shader = SKShader.CreateSweepGradient(center, GradientProperty.Value.GetColorsArray(), - GradientProperty.Value.GetColorPositionsArray(), SKShaderTileMode.Clamp, 0, 360); + GradientProperty.Value.GetPositionsArray(), SKShaderTileMode.Clamp, 0, 360); break; default: throw new ArgumentOutOfRangeException();