Nodes - Added gradient nodes

Nodes - Added color gradient pin type
Data bindings - Changed color gradient data bindings to now take a color gradient
This commit is contained in:
Robert committed 2022-09-23 21:41:08 +02:00
1 parent 32a444fbeb
commit 9c117d2773
48 files changed
+830 -344

No files matched your search

@@ -129,7 +129,7 @@ public class ArtemisIcon : UserControl
/// theme
/// </summary>
public static readonly StyledProperty<bool> FillProperty =
AvaloniaProperty.Register<ArtemisIcon, bool>(nameof(Icon), true, notifying: IconChanging);
AvaloniaProperty.Register<ArtemisIcon, bool>(nameof(Icon), false, notifying: IconChanging);
/// <summary>
/// Gets or sets a boolean indicating whether or not the icon should be filled in with the primary text color of the
@@ -59,22 +59,29 @@ public class GradientPicker : TemplatedControl
public static readonly DirectProperty<GradientPicker, ICommand> DeleteStopProperty =
AvaloniaProperty.RegisterDirect<GradientPicker, ICommand>(nameof(DeleteStop), g => g.DeleteStop);
/// <summary>
/// Gets the color gradient currently being edited, for internal use only
/// </summary>
public static readonly DirectProperty<GradientPicker, ColorGradient> EditingColorGradientProperty =
AvaloniaProperty.RegisterDirect<GradientPicker, ColorGradient>(nameof(EditingColorGradient), g => g.EditingColorGradient);
private readonly ICommand _deleteStop;
private ColorPicker? _colorPicker;
private Button? _flipStops;
private Border? _gradient;
private ColorGradient? _lastColorGradient;
private Button? _randomize;
private Button? _rotateStops;
private bool _shiftDown;
private Button? _spreadStops;
private Button? _toggleSeamless;
private ColorGradient _colorGradient = null!;
/// <summary>
/// Creates a new instance of the <see cref="GradientPicker" /> class.
/// </summary>
public GradientPicker()
{
EditingColorGradient = ColorGradient.GetUnicornBarf();
_deleteStop = ReactiveCommand.Create<ColorGradientStop>(s =>
{
if (ColorGradient.Count <= 2)
@@ -143,6 +150,15 @@ public class GradientPicker : TemplatedControl
get => _deleteStop;
private init => SetAndRaise(DeleteStopProperty, ref _deleteStop, value);
}
/// <summary>
/// Gets the color gradient backing the editor, this is a copy of <see cref="ColorGradient"/>.
/// </summary>
public ColorGradient EditingColorGradient
{
get => _colorGradient;
private set => SetAndRaise(EditingColorGradientProperty, ref _colorGradient, value);
}
/// <inheritdoc />
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
@@ -167,7 +183,7 @@ public class GradientPicker : TemplatedControl
_flipStops = e.NameScope.Find<Button>("FlipStops");
_rotateStops = e.NameScope.Find<Button>("RotateStops");
_randomize = e.NameScope.Find<Button>("Randomize");
if (_gradient != null)
_gradient.PointerPressed += GradientOnPointerPressed;
if (_spreadStops != null)
@@ -188,7 +204,7 @@ public class GradientPicker : TemplatedControl
/// <inheritdoc />
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
Subscribe();
ApplyToField();
KeyUp += OnKeyUp;
KeyDown += OnKeyDown;
@@ -197,60 +213,72 @@ public class GradientPicker : TemplatedControl
/// <inheritdoc />
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
Unsubscribe();
ApplyToProperty();
KeyUp -= OnKeyUp;
KeyDown -= OnKeyDown;
_shiftDown = false;
}
private static void ColorGradientChanged(IAvaloniaObject sender, bool before)
{
(sender as GradientPicker)?.Subscribe();
(sender as GradientPicker)?.ApplyToField();
}
private static void StorageProviderChanged(IAvaloniaObject sender, bool before)
{
}
private void Subscribe()
private void ApplyToField()
{
Unsubscribe();
ColorGradient.CollectionChanged += ColorGradientOnCollectionChanged;
ColorGradient.StopChanged += ColorGradientOnStopChanged;
SelectedColorStop = ColorGradient.FirstOrDefault();
EditingColorGradient = new ColorGradient(ColorGradient);
EditingColorGradient.CollectionChanged += ColorGradientOnCollectionChanged;
EditingColorGradient.StopChanged += ColorGradientOnStopChanged;
SelectedColorStop = EditingColorGradient.FirstOrDefault();
UpdateGradient();
_lastColorGradient = ColorGradient;
}
private void Unsubscribe()
private void ApplyToProperty()
{
if (_lastColorGradient == null)
return;
// Remove extra color gradients
while (ColorGradient.Count > EditingColorGradient.Count)
ColorGradient.RemoveAt(ColorGradient.Count - 1);
_lastColorGradient.CollectionChanged -= ColorGradientOnCollectionChanged;
_lastColorGradient.StopChanged -= ColorGradientOnStopChanged;
_lastColorGradient = null;
for (int index = 0; index < EditingColorGradient.Count; index++)
{
ColorGradientStop colorGradientStop = EditingColorGradient[index];
// Add missing color gradients
if (index >= ColorGradient.Count)
{
ColorGradient.Add(new ColorGradientStop(colorGradientStop.Color, colorGradientStop.Position));
}
// Update existing color gradients
else
{
ColorGradient[index].Color = colorGradientStop.Color;
ColorGradient[index].Position = colorGradientStop.Position;
}
}
}
private void ColorGradientOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
UpdateGradient();
ApplyToProperty();
}
private void ColorGradientOnStopChanged(object? sender, EventArgs e)
{
UpdateGradient();
ApplyToProperty();
}
private void UpdateGradient()
{
// Update the display gradient
GradientStops collection = new();
foreach (ColorGradientStop c in ColorGradient.OrderBy(s => s.Position))
foreach (ColorGradientStop c in EditingColorGradient.OrderBy(s => s.Position))
collection.Add(new GradientStop(Color.FromArgb(c.Color.Alpha, c.Color.Red, c.Color.Green, c.Color.Blue), c.Position));
LinearGradientBrush.GradientStops = collection;
@@ -263,8 +291,8 @@ public class GradientPicker : TemplatedControl
float position = (float) (e.GetPosition(_gradient).X / _gradient.Bounds.Width);
ColorGradientStop newStop = new(ColorGradient.GetColor(position), position);
ColorGradient.Add(newStop);
ColorGradientStop newStop = new(EditingColorGradient.GetColor(position), position);
EditingColorGradient.Add(newStop);
SelectedColorStop = newStop;
}
@@ -279,50 +307,50 @@ public class GradientPicker : TemplatedControl
if (e.Key is Key.LeftShift or Key.RightShift)
_shiftDown = false;
if (e.Key != Key.Delete || SelectedColorStop == null || ColorGradient.Count <= 2)
if (e.Key != Key.Delete || SelectedColorStop == null || EditingColorGradient.Count <= 2)
return;
int index = ColorGradient.IndexOf(SelectedColorStop);
ColorGradient.Remove(SelectedColorStop);
if (index > ColorGradient.Count - 1)
int index = EditingColorGradient.IndexOf(SelectedColorStop);
EditingColorGradient.Remove(SelectedColorStop);
if (index > EditingColorGradient.Count - 1)
index--;
SelectedColorStop = ColorGradient.ElementAtOrDefault(index);
SelectedColorStop = EditingColorGradient.ElementAtOrDefault(index);
e.Handled = true;
}
private void SpreadStopsOnClick(object? sender, RoutedEventArgs e)
{
ColorGradient.SpreadStops();
EditingColorGradient.SpreadStops();
}
private void ToggleSeamlessOnClick(object? sender, RoutedEventArgs e)
{
if (SelectedColorStop == null || ColorGradient.Count < 2)
if (SelectedColorStop == null || EditingColorGradient.Count < 2)
return;
ColorGradient.ToggleSeamless();
EditingColorGradient.ToggleSeamless();
}
private void FlipStopsOnClick(object? sender, RoutedEventArgs e)
{
if (SelectedColorStop == null || ColorGradient.Count < 2)
if (SelectedColorStop == null || EditingColorGradient.Count < 2)
return;
ColorGradient.FlipStops();
EditingColorGradient.FlipStops();
}
private void RotateStopsOnClick(object? sender, RoutedEventArgs e)
{
if (SelectedColorStop == null || ColorGradient.Count < 2)
if (SelectedColorStop == null || EditingColorGradient.Count < 2)
return;
ColorGradient.RotateStops(_shiftDown);
EditingColorGradient.RotateStops(_shiftDown);
}
private void RandomizeOnClick(object? sender, RoutedEventArgs e)
{
ColorGradient.Randomize(6);
SelectedColorStop = ColorGradient.First();
EditingColorGradient.Randomize(6);
SelectedColorStop = EditingColorGradient.First();
}
}
@@ -46,9 +46,6 @@ public class GradientPickerButton : TemplatedControl
AvaloniaProperty.RegisterDirect<GradientPickerButton, LinearGradientBrush>(nameof(LinearGradientBrush), g => g.LinearGradientBrush);
private Button? _button;
private GradientPickerFlyout? _flyout;
private bool _flyoutActive;
private ColorGradient? _lastColorGradient;
/// <summary>
@@ -150,27 +147,23 @@ public class GradientPickerButton : TemplatedControl
private void OnButtonClick(object? sender, RoutedEventArgs e)
{
if (_flyout == null || ColorGradient == null)
if (ColorGradient == null)
return;
// Logic here is taken from Fluent Avalonia's ColorPicker which also reuses the same control since it's large
_flyout.GradientPicker.ColorGradient = ColorGradient;
_flyout.GradientPicker.IsCompact = IsCompact;
_flyout.GradientPicker.StorageProvider = StorageProvider;
_flyout.ShowAt(this);
_flyoutActive = true;
GradientPickerFlyout flyout = new();
flyout.FlyoutPresenterClasses.Add("gradient-picker-presenter");
flyout.GradientPicker.ColorGradient = ColorGradient;
flyout.GradientPicker.IsCompact = IsCompact;
flyout.GradientPicker.StorageProvider = StorageProvider;
flyout.Closed += FlyoutOnClosed;
flyout.ShowAt(this);
FlyoutOpened?.Invoke(this, EventArgs.Empty);
}
private void OnFlyoutClosed(object? sender, EventArgs e)
{
if (_flyoutActive)
void FlyoutOnClosed(object? closedSender, EventArgs closedEventArgs)
{
flyout.Closed -= FlyoutOnClosed;
FlyoutClosed?.Invoke(this, EventArgs.Empty);
_flyoutActive = false;
}
}
@@ -191,22 +184,12 @@ public class GradientPickerButton : TemplatedControl
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
Subscribe();
if (_flyout == null)
{
_flyout = new GradientPickerFlyout();
_flyout.FlyoutPresenterClasses.Add("gradient-picker-presenter");
}
_flyout.Closed += OnFlyoutClosed;
}
/// <inheritdoc />
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
Unsubscribe();
if (_flyout != null)
_flyout.Closed -= OnFlyoutClosed;
}
#endregion
@@ -19,7 +19,7 @@ public class UpdateColorGradient : IProfileEditorCommand
public UpdateColorGradient(ColorGradient colorGradient, List<ColorGradientStop> stops, List<ColorGradientStop>? originalStops)
{
_colorGradient = colorGradient;
_stops = stops;
_stops = stops.Select(s => new ColorGradientStop(s.Color, s.Position)).ToList();
_originalStops = originalStops ?? _colorGradient.Select(s => new ColorGradientStop(s.Color, s.Position)).ToList();
}
@@ -31,18 +31,36 @@ public class UpdateColorGradient : IProfileEditorCommand
/// <inheritdoc />
public void Execute()
{
_colorGradient.Clear();
foreach (ColorGradientStop colorGradientStop in _stops)
_colorGradient.Add(colorGradientStop);
ApplyStops(_stops);
}
/// <inheritdoc />
public void Undo()
{
_colorGradient.Clear();
foreach (ColorGradientStop colorGradientStop in _originalStops)
_colorGradient.Add(colorGradientStop);
ApplyStops(_originalStops);
}
#endregion
private void ApplyStops(List<ColorGradientStop> stops)
{
while (_colorGradient.Count > stops.Count)
_colorGradient.RemoveAt(_colorGradient.Count - 1);
for (int index = 0; index < stops.Count; index++)
{
ColorGradientStop colorGradientStop = stops[index];
// Add missing color gradients
if (index >= _colorGradient.Count)
{
_colorGradient.Add(new ColorGradientStop(colorGradientStop.Color, colorGradientStop.Position));
}
// Update existing color gradients
else
{
_colorGradient[index].Color = colorGradientStop.Color;
_colorGradient[index].Position = colorGradientStop.Position;
}
}
}
}
@@ -73,7 +73,6 @@
<Style Selector="gradientPicker|GradientPicker">
<Style.Resources>
<converters:ColorGradientToGradientStopsConverter x:Key="ColorGradientToGradientStopsConverter" />
<converters:SKColorToColorConverter x:Key="SKColorToColorConverter" />
<converters:SKColorToBrushConverter x:Key="SKColorToBrushConverter" />
<converters:SKColorToStringConverter x:Key="SKColorToStringConverter" />
@@ -89,7 +88,7 @@
Background="{DynamicResource LightCheckerboardBrush}"
Margin="5 0">
<Border Background="{TemplateBinding LinearGradientBrush}">
<ItemsControl Name="GradientStops" Items="{TemplateBinding ColorGradient}" ClipToBounds="False">
<ItemsControl Name="GradientStops" Items="{TemplateBinding EditingColorGradient}" ClipToBounds="False">
<ItemsControl.Styles>
<Style Selector="ItemsControl#GradientStops > ContentPresenter">
<Setter Property="Canvas.Left">
@@ -105,9 +104,9 @@
<ItemsControl.ItemTemplate>
<DataTemplate DataType="core:ColorGradientStop">
<gradientPicker:GradientPickerColorStop ColorStop="{Binding}"
PositionReference="{Binding $parent[Border]}"
Classes="gradient-handle"
GradientPicker="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type gradientPicker:GradientPicker}}}">
PositionReference="{Binding $parent[Border]}"
Classes="gradient-handle"
GradientPicker="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type gradientPicker:GradientPicker}}}">
</gradientPicker:GradientPickerColorStop>
</DataTemplate>
</ItemsControl.ItemTemplate>
@@ -135,7 +134,7 @@
Grid.Column="0"
Grid.ColumnSpan="2"
VerticalAlignment="Center"
Items="{TemplateBinding ColorGradient}"
Items="{TemplateBinding EditingColorGradient}"
ClipToBounds="False"
Margin="5 0">
<ItemsControl.Styles>
@@ -180,9 +179,10 @@
</Border>
<Grid Grid.Row="2" Grid.Column="1" RowDefinitions="*,Auto">
<ListBox Grid.Row="0"
<ListBox Name="GradientColors"
Grid.Row="0"
MaxHeight="280"
Items="{TemplateBinding ColorGradient}"
Items="{TemplateBinding EditingColorGradient}"
SelectedItem="{TemplateBinding SelectedColorStop, Mode=TwoWay}"
Padding="10 0 15 0">
<ListBox.ItemTemplate>
@@ -201,7 +201,7 @@
<TextBox Grid.Column="1" Text="{Binding Color, Converter={StaticResource SKColorToStringConverter}}" />
<NumericUpDown Grid.Column="2" FormatString="F3" ShowButtonSpinner="False" Margin="5 0" Minimum="0" Maximum="1" Increment="0.01">
<Interaction.Behaviors>
<behaviors:LostFocusNumericUpDownBindingBehavior Value="{Binding Position}"/>
<behaviors:LostFocusNumericUpDownBindingBehavior Value="{Binding Position}" />
</Interaction.Behaviors>
</NumericUpDown>
<Button Name="DeleteButton"