diff --git a/src/Artemis.UI.Shared/AnimationTimeline/BrushAnimation.cs b/src/Artemis.UI.Shared/AnimationTimeline/BrushAnimation.cs
new file mode 100644
index 000000000..094243472
--- /dev/null
+++ b/src/Artemis.UI.Shared/AnimationTimeline/BrushAnimation.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+
+namespace Artemis.UI.Shared.AnimationTimeline
+{
+ public class BrushAnimation : System.Windows.Media.Animation.AnimationTimeline
+ {
+ public static readonly DependencyProperty FromProperty =
+ DependencyProperty.Register("From", typeof(Brush), typeof(BrushAnimation));
+
+ public static readonly DependencyProperty ToProperty =
+ DependencyProperty.Register("To", typeof(Brush), typeof(BrushAnimation));
+
+ public override Type TargetPropertyType => typeof(Brush);
+
+ //we must define From and To, AnimationTimeline does not have this properties
+ public Brush From
+ {
+ get => (Brush) GetValue(FromProperty);
+ set => SetValue(FromProperty, value);
+ }
+
+ public Brush To
+ {
+ get => (Brush) GetValue(ToProperty);
+ set => SetValue(ToProperty, value);
+ }
+
+ public override object GetCurrentValue(object defaultOriginValue,
+ object defaultDestinationValue,
+ AnimationClock animationClock)
+ {
+ return GetCurrentValue(defaultOriginValue as Brush,
+ defaultDestinationValue as Brush,
+ animationClock);
+ }
+
+ public object GetCurrentValue(Brush defaultOriginValue,
+ Brush defaultDestinationValue,
+ AnimationClock animationClock)
+ {
+ if (!animationClock.CurrentProgress.HasValue)
+ return Brushes.Transparent;
+
+ //use the standard values if From and To are not set
+ //(it is the value of the given property)
+ defaultOriginValue = From ?? defaultOriginValue;
+ defaultDestinationValue = To ?? defaultDestinationValue;
+
+ if (animationClock.CurrentProgress.Value == 0)
+ return defaultOriginValue;
+ if (animationClock.CurrentProgress.Value == 1)
+ return defaultDestinationValue;
+
+ return new VisualBrush(new Border
+ {
+ Width = 1,
+ Height = 1,
+ Background = defaultOriginValue,
+ Child = new Border
+ {
+ Background = defaultDestinationValue,
+ Opacity = animationClock.CurrentProgress.Value
+ }
+ });
+ }
+
+ protected override Freezable CreateInstanceCore()
+ {
+ return new BrushAnimation();
+ }
+ }
+}
\ 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
index cb2854546..be290ccf5 100644
--- a/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopView.xaml
+++ b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopView.xaml
@@ -6,20 +6,61 @@
xmlns:local="clr-namespace:Artemis.UI.Shared.Screens.GradientEditor"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters"
+ xmlns:utilities="clr-namespace:Artemis.UI.Shared.Utilities"
+ xmlns:animationTimeline="clr-namespace:Artemis.UI.Shared.AnimationTimeline"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
- d:DataContext="{d:DesignInstance local:ColorStopViewModel}">
+ d:DataContext="{d:DesignInstance local:ColorStopViewModel}" Opacity="1">
+
-
+ MouseMove="{s:Action StopMouseMove}">
+
+
+
diff --git a/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs
index cafdfca8d..67227cfd1 100644
--- a/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs
+++ b/src/Artemis.UI.Shared/Screens/GradientEditor/ColorStopViewModel.cs
@@ -1,10 +1,12 @@
using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
using System.Windows;
+using System.Windows.Controls;
using System.Windows.Input;
-using System.Windows.Media;
using Artemis.Core.Models.Profile;
-using PropertyChanged;
-using SkiaSharp;
+using Artemis.UI.Shared.Utilities;
using Stylet;
namespace Artemis.UI.Shared.Screens.GradientEditor
@@ -12,69 +14,107 @@ namespace Artemis.UI.Shared.Screens.GradientEditor
public class ColorStopViewModel : PropertyChangedBase
{
private readonly GradientEditorViewModel _gradientEditorViewModel;
+ private bool _isSelected;
+ private bool _willRemoveColorStop;
- public ColorStopViewModel(GradientEditorViewModel gradientEditorViewModel)
+ public ColorStopViewModel(GradientEditorViewModel gradientEditorViewModel, ColorGradientStop colorStop)
{
_gradientEditorViewModel = gradientEditorViewModel;
+ ColorStop = colorStop;
+ ColorStop.PropertyChanged += ColorStopOnPropertyChanged;
}
- public ColorGradientStop ColorStop { get; set; }
- public double Offset => ColorStop.Position * _gradientEditorViewModel.PreviewWidth;
- public SKColor Color => ColorStop.Color;
+ private void ColorStopOnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ _gradientEditorViewModel.ColorGradient.OnColorValuesUpdated();
+ }
+
+ public ColorGradientStop ColorStop { get; }
+
+ public double Offset
+ {
+ get => ColorStop.Position * _gradientEditorViewModel.PreviewWidth;
+ set
+ {
+ ColorStop.Position = (float) Math.Round(value / _gradientEditorViewModel.PreviewWidth, 3, MidpointRounding.AwayFromZero);
+ NotifyOfPropertyChange(nameof(Offset));
+ NotifyOfPropertyChange(nameof(OffsetPercent));
+ }
+ }
+
+ public float OffsetPercent
+ {
+ get => (float) Math.Round(ColorStop.Position * 100.0, MidpointRounding.AwayFromZero);
+ set
+ {
+ ColorStop.Position = Math.Min(100, Math.Max(0, value)) / 100f;
+ NotifyOfPropertyChange(nameof(Offset));
+ NotifyOfPropertyChange(nameof(OffsetPercent));
+ }
+ }
+
+ public bool IsSelected
+ {
+ get => _isSelected;
+ set => SetAndNotify(ref _isSelected, value);
+ }
+
+ public bool WillRemoveColorStop
+ {
+ get => _willRemoveColorStop;
+ set => SetAndNotify(ref _willRemoveColorStop, value);
+ }
#region Movement
-
- private double _mouseDownOffset;
- private DateTime _mouseDownTime;
-
+
public void StopMouseDown(object sender, MouseButtonEventArgs e)
{
- var position = GetPositionInPreview(sender, e);
+ e.Handled = true;
+
((IInputElement) sender).CaptureMouse();
- _mouseDownOffset = Offset - position.X;
- _mouseDownTime = DateTime.Now;
+ _gradientEditorViewModel.SelectColorStop(this);
}
public void StopMouseUp(object sender, MouseButtonEventArgs e)
{
- // On regular click, select this color stop
- if (DateTime.Now - _mouseDownTime <= TimeSpan.FromMilliseconds(250))
- {
- }
+ e.Handled = true;
((IInputElement) sender).ReleaseMouseCapture();
- e.Handled = true;
+ if (WillRemoveColorStop)
+ _gradientEditorViewModel.RemoveColorStop(this);
}
public void StopMouseMove(object sender, MouseEventArgs e)
{
+ e.Handled = true;
+
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));
+ var parent = VisualTreeUtilities.FindParent