mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-31 09:43:46 +00:00
Color picker - Avoid overlapping colors
This commit is contained in:
parent
212d13c1c8
commit
3efb97eedd
@ -51,6 +51,7 @@ public class ColorGradient : IList<ColorGradientStop>, IList, INotifyCollectionC
|
|||||||
{
|
{
|
||||||
ColorGradientStop stop = new(colorGradientStop.Color, colorGradientStop.Position);
|
ColorGradientStop stop = new(colorGradientStop.Color, colorGradientStop.Position);
|
||||||
stop.PropertyChanged += ItemOnPropertyChanged;
|
stop.PropertyChanged += ItemOnPropertyChanged;
|
||||||
|
stop.ColorGradient = this;
|
||||||
_stops.Add(stop);
|
_stops.Add(stop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,6 +67,7 @@ public class ColorGradient : IList<ColorGradientStop>, IList, INotifyCollectionC
|
|||||||
{
|
{
|
||||||
ColorGradientStop stop = new(colorGradientStop.Color, colorGradientStop.Position);
|
ColorGradientStop stop = new(colorGradientStop.Color, colorGradientStop.Position);
|
||||||
stop.PropertyChanged += ItemOnPropertyChanged;
|
stop.PropertyChanged += ItemOnPropertyChanged;
|
||||||
|
stop.ColorGradient = this;
|
||||||
_stops.Add(stop);
|
_stops.Add(stop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -465,6 +467,7 @@ public class ColorGradient : IList<ColorGradientStop>, IList, INotifyCollectionC
|
|||||||
public void Add(ColorGradientStop item)
|
public void Add(ColorGradientStop item)
|
||||||
{
|
{
|
||||||
_stops.Add(item);
|
_stops.Add(item);
|
||||||
|
item.ColorGradient = this;
|
||||||
item.PropertyChanged += ItemOnPropertyChanged;
|
item.PropertyChanged += ItemOnPropertyChanged;
|
||||||
|
|
||||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, _stops.IndexOf(item)));
|
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, _stops.IndexOf(item)));
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Artemis.Core;
|
namespace Artemis.Core;
|
||||||
@ -35,9 +36,11 @@ public class ColorGradientStop : CorePropertyChanged
|
|||||||
public float Position
|
public float Position
|
||||||
{
|
{
|
||||||
get => _position;
|
get => _position;
|
||||||
set => SetAndNotify(ref _position, value);
|
set => SetAndNotify(ref _position, GetUpdatedPosition(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal ColorGradient? ColorGradient { get; set; }
|
||||||
|
|
||||||
#region Equality members
|
#region Equality members
|
||||||
|
|
||||||
/// <inheritdoc cref="object.Equals(object)" />
|
/// <inheritdoc cref="object.Equals(object)" />
|
||||||
@ -64,5 +67,32 @@ public class ColorGradientStop : CorePropertyChanged
|
|||||||
return HashCode.Combine(_color, _position);
|
return HashCode.Combine(_color, _position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the position of the given color stop in a safe manner that avoids overlap with other stops.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stopPosition">The new position.</param>
|
||||||
|
private float GetUpdatedPosition(float stopPosition)
|
||||||
|
{
|
||||||
|
if (ColorGradient == null)
|
||||||
|
return stopPosition;
|
||||||
|
// Find the first available spot going down
|
||||||
|
while (ColorGradient.Any(s => !ReferenceEquals(s, this) && Math.Abs(s.Position - stopPosition) < 0.001f))
|
||||||
|
stopPosition -= 0.001f;
|
||||||
|
|
||||||
|
// If we ran out of space, try going up
|
||||||
|
if (stopPosition < 0)
|
||||||
|
{
|
||||||
|
stopPosition = 0;
|
||||||
|
while (ColorGradient.Any(s => !ReferenceEquals(s, this) && Math.Abs(s.Position - stopPosition) < 0.001f))
|
||||||
|
stopPosition += 0.001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we ran out of space there too, movement isn't possible
|
||||||
|
if (stopPosition > 1)
|
||||||
|
stopPosition = Position;
|
||||||
|
|
||||||
|
return stopPosition;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Data;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
using FluentAvalonia.UI.Controls;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Shared.Behaviors;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a behavior that can be used to make a numeric up down only update it's binding on focus loss.
|
||||||
|
/// </summary>
|
||||||
|
public class LostFocusNumericUpDownBindingBehavior : Behavior<NumericUpDown>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the binding.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly StyledProperty<double> ValueProperty = AvaloniaProperty.Register<LostFocusNumericUpDownBindingBehavior, double>(
|
||||||
|
nameof(Value), defaultBindingMode: BindingMode.TwoWay);
|
||||||
|
|
||||||
|
static LostFocusNumericUpDownBindingBehavior()
|
||||||
|
{
|
||||||
|
ValueProperty.Changed.Subscribe(e => ((LostFocusNumericUpDownBindingBehavior) e.Sender).OnBindingValueChanged());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the binding.
|
||||||
|
/// </summary>
|
||||||
|
public double Value
|
||||||
|
{
|
||||||
|
get => GetValue(ValueProperty);
|
||||||
|
set => SetValue(ValueProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnAttached()
|
||||||
|
{
|
||||||
|
if (AssociatedObject != null)
|
||||||
|
AssociatedObject.LostFocus += OnLostFocus;
|
||||||
|
base.OnAttached();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnDetaching()
|
||||||
|
{
|
||||||
|
if (AssociatedObject != null)
|
||||||
|
AssociatedObject.LostFocus -= OnLostFocus;
|
||||||
|
base.OnDetaching();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLostFocus(object? sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (AssociatedObject != null)
|
||||||
|
Value = AssociatedObject.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBindingValueChanged()
|
||||||
|
{
|
||||||
|
if (AssociatedObject != null)
|
||||||
|
AssociatedObject.Value = Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,7 +4,8 @@
|
|||||||
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
xmlns:core="clr-namespace:Artemis.Core;assembly=Artemis.Core"
|
||||||
xmlns:fluent="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:fluent="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Shared.Converters"
|
||||||
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker">
|
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker"
|
||||||
|
xmlns:behaviors="clr-namespace:Artemis.UI.Shared.Behaviors">
|
||||||
<Styles.Resources>
|
<Styles.Resources>
|
||||||
<VisualBrush x:Key="LightCheckerboardBrush" TileMode="Tile" Stretch="Uniform" DestinationRect="3,0,10,10">
|
<VisualBrush x:Key="LightCheckerboardBrush" TileMode="Tile" Stretch="Uniform" DestinationRect="3,0,10,10">
|
||||||
<VisualBrush.Visual>
|
<VisualBrush.Visual>
|
||||||
@ -198,7 +199,11 @@
|
|||||||
<Border CornerRadius="4" Margin="-2" Background="{Binding Color, Converter={StaticResource SKColorToBrushConverter}}" />
|
<Border CornerRadius="4" Margin="-2" Background="{Binding Color, Converter={StaticResource SKColorToBrushConverter}}" />
|
||||||
</Border>
|
</Border>
|
||||||
<TextBox Grid.Column="1" Text="{Binding Color, Converter={StaticResource SKColorToStringConverter}}" />
|
<TextBox Grid.Column="1" Text="{Binding Color, Converter={StaticResource SKColorToStringConverter}}" />
|
||||||
<NumericUpDown Grid.Column="2" Value="{Binding Position}" FormatString="F3" ShowButtonSpinner="False" Margin="5 0" />
|
<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}"/>
|
||||||
|
</Interaction.Behaviors>
|
||||||
|
</NumericUpDown>
|
||||||
<Button Name="DeleteButton"
|
<Button Name="DeleteButton"
|
||||||
Grid.Column="3"
|
Grid.Column="3"
|
||||||
Classes="icon-button"
|
Classes="icon-button"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user