更新
This commit is contained in:
155
WPFDark/Controls/BiaHsvWheelCursor.cs
Normal file
155
WPFDark/Controls/BiaHsvWheelCursor.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using WPFDark.Internals;
|
||||
|
||||
namespace WPFDark.Controls
|
||||
{
|
||||
public class BiaHsvWheelCursor : FrameworkElement
|
||||
{
|
||||
#region Hue
|
||||
|
||||
public double Hue
|
||||
{
|
||||
get => _Hue;
|
||||
set
|
||||
{
|
||||
if (NumberHelper.AreClose(value, _Hue) == false)
|
||||
SetValue(HueProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
private double _Hue;
|
||||
|
||||
public static readonly DependencyProperty HueProperty =
|
||||
DependencyProperty.Register(nameof(Hue), typeof(double), typeof(BiaHsvWheelCursor),
|
||||
new FrameworkPropertyMetadata(
|
||||
0.0,
|
||||
FrameworkPropertyMetadataOptions.AffectsRender |
|
||||
FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
|
||||
(s, e) =>
|
||||
{
|
||||
var self = (BiaHsvWheelCursor) s;
|
||||
self._Hue = (double) e.NewValue;
|
||||
}));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Saturation
|
||||
|
||||
public double Saturation
|
||||
{
|
||||
get => _Saturation;
|
||||
set
|
||||
{
|
||||
if (NumberHelper.AreClose(value, _Saturation) == false)
|
||||
SetValue(SaturationProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
private double _Saturation;
|
||||
|
||||
public static readonly DependencyProperty SaturationProperty =
|
||||
DependencyProperty.Register(nameof(Saturation), typeof(double), typeof(BiaHsvWheelCursor),
|
||||
new FrameworkPropertyMetadata(
|
||||
0.0,
|
||||
FrameworkPropertyMetadataOptions.AffectsRender |
|
||||
FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
|
||||
(s, e) =>
|
||||
{
|
||||
var self = (BiaHsvWheelCursor) s;
|
||||
self._Saturation = (double) e.NewValue;
|
||||
}));
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsReadOnly
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get => _IsReadOnly;
|
||||
set
|
||||
{
|
||||
if (value != _IsReadOnly)
|
||||
SetValue(IsReadOnlyProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _IsReadOnly;
|
||||
|
||||
public static readonly DependencyProperty IsReadOnlyProperty =
|
||||
DependencyProperty.Register(nameof(IsReadOnly), typeof(bool), typeof(BiaHsvWheelCursor),
|
||||
new FrameworkPropertyMetadata(
|
||||
false,
|
||||
FrameworkPropertyMetadataOptions.AffectsRender |
|
||||
FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
|
||||
(s, e) =>
|
||||
{
|
||||
var self = (BiaHsvWheelCursor) s;
|
||||
self._IsReadOnly = (bool) e.NewValue;
|
||||
}));
|
||||
|
||||
#endregion
|
||||
|
||||
static BiaHsvWheelCursor()
|
||||
{
|
||||
DefaultStyleKeyProperty.OverrideMetadata(typeof(BiaHsvWheelCursor),
|
||||
new FrameworkPropertyMetadata(typeof(BiaHsvWheelCursor)));
|
||||
}
|
||||
|
||||
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
|
||||
private readonly PropertyChangeNotifier _isEnabledChangeNotifier;
|
||||
|
||||
public BiaHsvWheelCursor()
|
||||
{
|
||||
IsHitTestVisible = false;
|
||||
|
||||
_isEnabledChangeNotifier = new PropertyChangeNotifier(this, IsEnabledProperty);
|
||||
_isEnabledChangeNotifier.ValueChanged += (_, __) => InvalidateVisual();
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext dc)
|
||||
{
|
||||
if (ActualWidth <= 1 ||
|
||||
ActualHeight <= 1)
|
||||
return;
|
||||
|
||||
var rounder = new LayoutRounder(this);
|
||||
|
||||
// Cursor
|
||||
this.DrawPointCursor(rounder, dc, MakeCursorRenderPos(rounder), IsEnabled, IsReadOnly);
|
||||
}
|
||||
|
||||
private ImmutableVec2_double MakeCursorRenderPos(in LayoutRounder rounder)
|
||||
=> MakeCursorRenderPos(rounder, ActualWidth, ActualHeight, Hue, Saturation);
|
||||
|
||||
internal static ImmutableVec2_double MakeCursorRenderPos(
|
||||
in LayoutRounder rounder,
|
||||
double actualWidth,
|
||||
double actualHeight,
|
||||
double hue,
|
||||
double saturation)
|
||||
{
|
||||
hue = NumberHelper.Clamp01(hue);
|
||||
saturation = NumberHelper.Clamp01(saturation);
|
||||
|
||||
var bw = rounder.RoundLayoutValue(FrameworkElementExtensions.BorderWidth);
|
||||
var w = rounder.RoundLayoutValue(actualWidth - bw * 2);
|
||||
var h = rounder.RoundLayoutValue(actualHeight - bw * 2);
|
||||
|
||||
var r = hue * 2.0 * Math.PI;
|
||||
|
||||
var (cx, cy) = MakeAspectRatioCorrection(actualWidth, actualHeight);
|
||||
|
||||
var x = bw + Math.Cos(r) * saturation * (w * 0.5) / cx + w * 0.5;
|
||||
var y = bw + Math.Sin(r) * saturation * (h * 0.5) / cy + h * 0.5;
|
||||
|
||||
return new ImmutableVec2_double(rounder.RoundLayoutValue(x), rounder.RoundLayoutValue(y));
|
||||
}
|
||||
|
||||
internal static (double X, double Y) MakeAspectRatioCorrection(double actualWidth, double actualHeight)
|
||||
=> actualWidth > actualHeight
|
||||
? (actualWidth / actualHeight, 1.0)
|
||||
: (1.0, actualHeight / actualWidth);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user