更新
This commit is contained in:
408
WPFDark/Controls/BiaHsvBoxBackground.cs
Normal file
408
WPFDark/Controls/BiaHsvBoxBackground.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user