This commit is contained in:
ShrlAlgo
2025-07-11 09:20:23 +08:00
parent c7b104f44f
commit 4d35cadb56
840 changed files with 102347 additions and 11595 deletions

View File

@@ -0,0 +1,408 @@
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using WPFDark.Controls.Effects;
using WPFDark.Internals;
namespace WPFDark.Controls
{
internal class BiaHsvBoxBackground : Canvas
{
#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(BiaHsvBoxBackground),
new FrameworkPropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaHsvBoxBackground) 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(BiaHsvBoxBackground),
new FrameworkPropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaHsvBoxBackground) s;
self.saturation = (double) e.NewValue;
}));
#endregion
#region Value
public double Value
{
get => value;
set
{
if (NumberHelper.AreClose(value, this.value) == false)
SetValue(ValueProperty, value);
}
}
private double value;
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(nameof(Value), typeof(double), typeof(BiaHsvBoxBackground),
new FrameworkPropertyMetadata(
0.0,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
(s, e) =>
{
var self = (BiaHsvBoxBackground) s;
self.value = (double) e.NewValue;
self.effect.Value = NumberHelper.Clamp01(self.value);
}));
#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(BiaHsvBoxBackground),
new FrameworkPropertyMetadata(
false,
FrameworkPropertyMetadataOptions.AffectsRender |
FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
(s, e) =>
{
var self = (BiaHsvBoxBackground) s;
self.isReadOnly = (bool) e.NewValue;
}));
#endregion
#region StartedContinuousEditingCommand
public ICommand? StartedContinuousEditingCommand
{
get => startedContinuousEditingCommand;
set
{
if (value != startedContinuousEditingCommand)
SetValue(StartedContinuousEditingCommandProperty, value);
}
}
private ICommand? startedContinuousEditingCommand;
public static readonly DependencyProperty StartedContinuousEditingCommandProperty =
DependencyProperty.Register(
nameof(StartedContinuousEditingCommand),
typeof(ICommand),
typeof(BiaHsvBoxBackground),
new PropertyMetadata(
default(ICommand),
(s, e) =>
{
var self = (BiaHsvBoxBackground) s;
self.startedContinuousEditingCommand = (ICommand) e.NewValue;
}));
#endregion
#region EndContinuousEditingCommand
public ICommand? EndContinuousEditingCommand
{
get => endContinuousEditingCommand;
set
{
if (value != endContinuousEditingCommand)
SetValue(EndContinuousEditingCommandProperty, value);
}
}
private ICommand? endContinuousEditingCommand;
public static readonly DependencyProperty EndContinuousEditingCommandProperty =
DependencyProperty.Register(
nameof(EndContinuousEditingCommand),
typeof(ICommand),
typeof(BiaHsvBoxBackground),
new PropertyMetadata(
default(ICommand),
(s, e) =>
{
var self = (BiaHsvBoxBackground) s;
self.endContinuousEditingCommand = (ICommand) e.NewValue;
}));
#endregion
#region StartedBatchEditingCommand
public ICommand? StartedBatchEditingCommand
{
get => startedBatchEditingCommand;
set
{
if (value != startedBatchEditingCommand)
SetValue(StartedBatchEditingCommandProperty, value);
}
}
private ICommand? startedBatchEditingCommand;
public static readonly DependencyProperty StartedBatchEditingCommandProperty =
DependencyProperty.Register(
nameof(StartedBatchEditingCommand),
typeof(ICommand),
typeof(BiaHsvBoxBackground),
new PropertyMetadata(
default(ICommand),
(s, e) =>
{
var self = (BiaHsvBoxBackground) s;
self.startedBatchEditingCommand = (ICommand) e.NewValue;
}));
#endregion
#region EndBatchEditingCommand
public ICommand? EndBatchEditingCommand
{
get => endBatchEditingCommand;
set
{
if (value != endBatchEditingCommand)
SetValue(EndBatchEditingCommandProperty, value);
}
}
private ICommand? endBatchEditingCommand;
public static readonly DependencyProperty EndBatchEditingCommandProperty =
DependencyProperty.Register(
nameof(EndBatchEditingCommand),
typeof(ICommand),
typeof(BiaHsvBoxBackground),
new PropertyMetadata(
default(ICommand),
(s, e) =>
{
var self = (BiaHsvBoxBackground) s;
self.endBatchEditingCommand = (ICommand) e.NewValue;
}));
#endregion
private readonly HsvBoxBackgroundEffect effect = new ();
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
private readonly PropertyChangeNotifier isEnabledChangeNotifier;
static BiaHsvBoxBackground()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BiaHsvBoxBackground),
new FrameworkPropertyMetadata(typeof(BiaHsvBoxBackground)));
}
public BiaHsvBoxBackground()
{
Effect = effect;
RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
effect.DisableColor = ((ByteColor)ThemeManager.Current.TryFindResource("InactiveColorPickerColorKey")).ToPoint3D();
isEnabledChangeNotifier = new PropertyChangeNotifier(this, IsEnabledProperty);
isEnabledChangeNotifier.ValueChanged += (_, _) =>
{
effect.IsEnabled = IsEnabled ? 1.0f : 0.0f;
InvalidateVisual();
};
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (ActualWidth <= 1 ||
ActualHeight <= 1)
return;
var rounder = new LayoutRounder(this);
var rect = rounder.RoundRenderRectangle(true);
dc.DrawRectangle(Brushes.Transparent, null, rect);
}
private void UpdateParams(in LayoutRounder rounder, MouseEventArgs e)
{
var pos = e.GetPosition(this);
var s = rounder.RoundLayoutValue(1);
var x = (pos.X - s) / (ActualWidth - s * 2);
var y = (pos.Y - s) / (ActualHeight - s * 2);
x = NumberHelper.Clamp01(x);
y = NumberHelper.Clamp01(y);
Hue = x;
Saturation = 1 - y;
}
private bool isMouseDown;
private bool isContinuousEdited;
private (double, double) continuousEditingStartValue;
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (IsReadOnly)
return;
isMouseDown = true;
GuiHelper.HideCursor();
var rounder = new LayoutRounder(this);
continuousEditingStartValue = (Hue, Saturation);
isContinuousEdited = true;
StartedContinuousEditingCommand?.ExecuteIfCan(null);
UpdateParams(rounder, e);
CaptureMouse();
this.SetMouseClipping();
e.Handled = true;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (IsReadOnly)
return;
if (isMouseDown == false)
return;
var rounder = new LayoutRounder(this);
UpdateParams(rounder, e);
e.Handled = true;
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (IsReadOnly)
return;
if (isMouseDown == false)
return;
// マウス位置を補正する
{
var rounder = new LayoutRounder(this);
var pos = BiaHsvBoxCursor.MakeCursorRenderPos(rounder, ActualWidth, ActualHeight, Hue, Saturation);
var mousePos = PointToScreen(Unsafe.As<ImmutableVec2_double, Point>(ref pos));
Win32Helper.SetCursorPos((int) mousePos.X, (int) mousePos.Y);
}
isMouseDown = false;
GuiHelper.ShowCursor();
this.ResetMouseClipping();
ReleaseMouseCapture();
if (isContinuousEdited)
{
if (EndContinuousEditingCommand != null)
{
if (EndContinuousEditingCommand.CanExecute(null))
{
var changedValue = (Hue, Saturation);
(Hue, Saturation) = continuousEditingStartValue;
EndContinuousEditingCommand.Execute(null);
StartedBatchEditingCommand?.ExecuteIfCan(null);
(Hue, Saturation) = changedValue;
EndBatchEditingCommand?.ExecuteIfCan(null);
}
}
isContinuousEdited = false;
}
e.Handled = true;
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
if (isMouseDown)
{
isMouseDown = false;
ReleaseMouseCapture();
GuiHelper.ShowCursor();
this.ResetMouseClipping();
}
e.Handled = true;
}
}
}