Files
Shrlalgo.RvKits/WPFDark/Controls/BiaColorPicker.cs
ShrlAlgo 4d35cadb56 更新
2025-07-11 09:20:23 +08:00

876 lines
26 KiB
C#

using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using WPFDark.Internals;
namespace WPFDark.Controls
{
public class BiaColorPicker : Control
{
#region Red
public double Red
{
get => red;
set
{
if (NumberHelper.AreClose(value, red) == false)
SetValue(RedProperty, value);
}
}
private double red;
public static readonly DependencyProperty RedProperty =
DependencyProperty.Register(nameof(Red), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.red = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region Green
public double Green
{
get => green;
set
{
if (NumberHelper.AreClose(value, green) == false)
SetValue(GreenProperty, value);
}
}
private double green;
public static readonly DependencyProperty GreenProperty =
DependencyProperty.Register(nameof(Green), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.green = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region Blue
public double Blue
{
get => blue;
set
{
if (NumberHelper.AreClose(value, blue) == false)
SetValue(BlueProperty, value);
}
}
private double blue;
public static readonly DependencyProperty BlueProperty =
DependencyProperty.Register(nameof(Blue), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.blue = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region Alpha
public double Alpha
{
get => alpha;
set
{
if (NumberHelper.AreClose(value, alpha) == false)
SetValue(AlphaProperty, value);
}
}
private double alpha;
public static readonly DependencyProperty AlphaProperty =
DependencyProperty.Register(nameof(Alpha), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.alpha = (double) e.NewValue;
}));
#endregion
#region RedMaximum
public double RedMaximum
{
get => redMaximum;
set
{
if (NumberHelper.AreClose(value, redMaximum) == false)
SetValue(RedMaximumProperty, value);
}
}
private double redMaximum = 1.0;
public static readonly DependencyProperty RedMaximumProperty =
DependencyProperty.Register(nameof(RedMaximum), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
1.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.redMaximum = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region GreenMaximum
public double GreenMaximum
{
get => greenMaximum;
set
{
if (NumberHelper.AreClose(value, greenMaximum) == false)
SetValue(GreenMaximumProperty, value);
}
}
private double greenMaximum = 1.0;
public static readonly DependencyProperty GreenMaximumProperty =
DependencyProperty.Register(nameof(GreenMaximum), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
1.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.greenMaximum = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region BlueMaximum
public double BlueMaximum
{
get => blueMaximum;
set
{
if (NumberHelper.AreClose(value, blueMaximum) == false)
SetValue(BlueMaximumProperty, value);
}
}
private double blueMaximum = 1.0;
public static readonly DependencyProperty BlueMaximumProperty =
DependencyProperty.Register(nameof(BlueMaximum), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
1.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.blueMaximum = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region AlphaMaximum
public double AlphaMaximum
{
get => alphaMaximum;
set
{
if (NumberHelper.AreClose(value, alphaMaximum) == false)
SetValue(AlphaMaximumProperty, value);
}
}
private double alphaMaximum = 1.0;
public static readonly DependencyProperty AlphaMaximumProperty =
DependencyProperty.Register(nameof(AlphaMaximum), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
1.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.alphaMaximum = (double) e.NewValue;
}));
#endregion
#region RedMinimum
public double RedMinimum
{
get => redMinimum;
set
{
if (NumberHelper.AreClose(value, redMinimum) == false)
SetValue(RedMinimumProperty, value);
}
}
private double redMinimum;
public static readonly DependencyProperty RedMinimumProperty =
DependencyProperty.Register(nameof(RedMinimum), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.redMinimum = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region GreenMinimum
public double GreenMinimum
{
get => greenMinimum;
set
{
if (NumberHelper.AreClose(value, greenMinimum) == false)
SetValue(GreenMinimumProperty, value);
}
}
private double greenMinimum;
public static readonly DependencyProperty GreenMinimumProperty =
DependencyProperty.Register(nameof(GreenMinimum), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self.greenMinimum = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region BlueMinimum
public double BlueMinimum
{
get => _BlueMinimum;
set
{
if (NumberHelper.AreClose(value, _BlueMinimum) == false)
SetValue(BlueMinimumProperty, value);
}
}
private double _BlueMinimum;
public static readonly DependencyProperty BlueMinimumProperty =
DependencyProperty.Register(nameof(BlueMinimum), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self._BlueMinimum = (double) e.NewValue;
self.RgbToHsv();
}));
#endregion
#region AlphaMinimum
public double AlphaMinimum
{
get => _AlphaMinimum;
set
{
if (NumberHelper.AreClose(value, _AlphaMinimum) == false)
SetValue(AlphaMinimumProperty, value);
}
}
private double _AlphaMinimum;
public static readonly DependencyProperty AlphaMinimumProperty =
DependencyProperty.Register(nameof(AlphaMinimum), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self._AlphaMinimum = (double) e.NewValue;
}));
#endregion
#region IsVisibleAlphaEditor
public bool IsVisibleAlphaEditor
{
get => _IsVisibleAlphaEditor;
set
{
if (value != _IsVisibleAlphaEditor)
SetValue(IsVisibleAlphaEditorProperty, value);
}
}
private bool _IsVisibleAlphaEditor = true;
public static readonly DependencyProperty IsVisibleAlphaEditorProperty =
DependencyProperty.Register(
nameof(IsVisibleAlphaEditor),
typeof(bool),
typeof(BiaColorPicker),
new PropertyMetadata(
true,
(s, e) =>
{
var self = (BiaColorPicker) s;
self._IsVisibleAlphaEditor = (bool) e.NewValue;
}));
#endregion
#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(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self._Hue = (double) e.NewValue;
self.HsvToRgb();
}));
#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(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self._Saturation = (double) e.NewValue;
self.HsvToRgb();
}));
#endregion
#region Value
public double Value
{
get => _Value;
set
{
if (NumberHelper.AreClose(value, _Value) == false)
SetValue(ValueProperty, value);
}
}
private double _Value;
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(nameof(Value), typeof(double), typeof(BiaColorPicker),
new PropertyMetadata(
0.0,
(s, e) =>
{
var self = (BiaColorPicker) s;
self._Value = (double) e.NewValue;
self.HsvToRgb();
}));
#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(BiaColorPicker),
new PropertyMetadata(
false,
(s, e) =>
{
var self = (BiaColorPicker) 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(BiaColorPicker),
new PropertyMetadata(
default(ICommand),
(s, e) =>
{
var self = (BiaColorPicker) 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(BiaColorPicker),
new PropertyMetadata(
default(ICommand),
(s, e) =>
{
var self = (BiaColorPicker) 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(BiaColorPicker),
new PropertyMetadata(
default(ICommand),
(s, e) =>
{
var self = (BiaColorPicker) s;
self._StartedBatchEditingCommand = (ICommand) e.NewValue;
if (self._wheelBackground != null)
self._wheelBackground.StartedBatchEditingCommand = self._StartedBatchEditingCommand;
if (self.boxBackground != null)
self.boxBackground.StartedBatchEditingCommand = self._StartedBatchEditingCommand;
}));
#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(BiaColorPicker),
new PropertyMetadata(
default(ICommand),
(s, e) =>
{
var self = (BiaColorPicker) s;
self._EndBatchEditingCommand = (ICommand) e.NewValue;
if (self._wheelBackground != null)
self._wheelBackground.EndBatchEditingCommand = self._EndBatchEditingCommand;
if (self.boxBackground != null)
self.boxBackground.EndBatchEditingCommand = self._EndBatchEditingCommand;
}));
#endregion
static BiaColorPicker()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BiaColorPicker),
new FrameworkPropertyMetadata(typeof(BiaColorPicker)));
}
public BiaColorPicker()
{
SizeChanged += (_, e) =>
{
if (redEditor is null)
return;
if (e.NewSize.Width > 300)
{
if (redEditor != null)
redEditor.Caption = "Red";
if (_greenEditor != null)
_greenEditor.Caption = "Green";
if (_blueEditor != null)
_blueEditor.Caption = "Blue";
if (_alphaEditor != null)
_alphaEditor.Caption = "Alpha";
if (_hueEditor != null)
_hueEditor.Caption = "Hue";
if (_saturationEditor != null)
_saturationEditor.Caption = "Saturation";
if (_valueEditor != null)
_valueEditor.Caption = "Value";
}
else
{
if (redEditor != null)
redEditor.Caption = "R";
if (_greenEditor != null)
_greenEditor.Caption = "G";
if (_blueEditor != null)
_blueEditor.Caption = "B";
if (_alphaEditor != null)
_alphaEditor.Caption = "A";
if (_hueEditor != null)
_hueEditor.Caption = "H";
if (_saturationEditor != null)
_saturationEditor.Caption = "S";
if (_valueEditor != null)
_valueEditor.Caption = "V";
}
};
}
public override void OnApplyTemplate()
{
foreach (var e in this.Descendants())
{
if (e is BiaNumberEditor numberEditor)
{
switch (numberEditor.Name)
{
case "RedEditor":
redEditor = numberEditor;
break;
case "GreenEditor":
_greenEditor = numberEditor;
break;
case "BlueEditor":
_blueEditor = numberEditor;
break;
case "AlphaEditor":
_alphaEditor = numberEditor;
break;
case "HueEditor":
_hueEditor = numberEditor;
break;
case "SaturationEditor":
_saturationEditor = numberEditor;
break;
case "ValueEditor":
_valueEditor = numberEditor;
break;
}
}
else if (_valueBar is null && e is BiaColorBar colorBar)
_valueBar = colorBar;
else if (_wheelBackground is null && e is BiaHsvWheelBackground hsvWheelBackground)
_wheelBackground = hsvWheelBackground;
else if (boxBackground is null && e is BiaHsvBoxBackground hsvBoxBackground)
boxBackground = hsvBoxBackground;
}
SetContinuousEditingCommand();
}
private BiaNumberEditor? redEditor;
private BiaNumberEditor? _greenEditor;
private BiaNumberEditor? _blueEditor;
private BiaNumberEditor? _alphaEditor;
private BiaNumberEditor? _hueEditor;
private BiaNumberEditor? _saturationEditor;
private BiaNumberEditor? _valueEditor;
private BiaColorBar? _valueBar;
private BiaHsvWheelBackground? _wheelBackground;
private BiaHsvBoxBackground? boxBackground;
private bool _isConverting;
private void RgbToHsv()
{
if (_isConverting)
return;
_isConverting = true;
StartedBatchEditingCommand?.ExecuteIfCan(null);
(Hue, Saturation, Value) = ColorSpaceHelper.RgbToHsv(Red, Green, Blue);
EndBatchEditingCommand?.ExecuteIfCan(null);
_isConverting = false;
}
private void HsvToRgb()
{
if (_isConverting)
return;
_isConverting = true;
StartedBatchEditingCommand?.ExecuteIfCan(null);
(Red, Green, Blue) = ColorSpaceHelper.HsvToRgb(Hue, Saturation, NumberHelper.Clamp01(Value));
EndBatchEditingCommand?.ExecuteIfCan(null);
_isConverting = false;
}
private int _editingDepth;
private (double, double, double) _continuousEditingStartValue;
private void SetContinuousEditingCommand()
{
var started = new DelegateCommand(() =>
{
if (_editingDepth == 0)
{
_continuousEditingStartValue = (Red, Green, Blue);
StartedContinuousEditingCommand?.ExecuteIfCan(null);
}
++_editingDepth;
});
var end = new DelegateCommand(() =>
{
Debug.Assert(_editingDepth > 0);
--_editingDepth;
if (_editingDepth == 0)
{
if (EndContinuousEditingCommand != null)
{
if (EndContinuousEditingCommand.CanExecute(null))
{
var changedValue = (Red, Green, Blue);
(Red, Green, Blue) = _continuousEditingStartValue;
EndContinuousEditingCommand.Execute(null);
(Red, Green, Blue) = changedValue;
}
}
}
});
if (redEditor != null)
{
redEditor.StartedContinuousEditingCommand = started;
redEditor.EndContinuousEditingCommand = end;
}
if (_greenEditor != null)
{
_greenEditor.StartedContinuousEditingCommand = started;
_greenEditor.EndContinuousEditingCommand = end;
}
if (_blueEditor != null)
{
_blueEditor.StartedContinuousEditingCommand = started;
_blueEditor.EndContinuousEditingCommand = end;
}
if (_alphaEditor != null)
{
_alphaEditor.StartedContinuousEditingCommand = started;
_alphaEditor.EndContinuousEditingCommand = end;
}
if (_hueEditor != null)
{
_hueEditor.StartedContinuousEditingCommand = started;
_hueEditor.EndContinuousEditingCommand = end;
}
if (_saturationEditor != null)
{
_saturationEditor.StartedContinuousEditingCommand = started;
_saturationEditor.EndContinuousEditingCommand = end;
}
if (_valueEditor != null)
{
_valueEditor.StartedContinuousEditingCommand = started;
_valueEditor.EndContinuousEditingCommand = end;
}
if (_valueBar != null)
{
_valueBar.StartedContinuousEditingCommand = started;
_valueBar.EndContinuousEditingCommand = end;
}
if (_wheelBackground != null)
{
_wheelBackground.StartedContinuousEditingCommand = started;
_wheelBackground.EndContinuousEditingCommand = end;
}
if (boxBackground != null)
{
boxBackground.StartedContinuousEditingCommand = started;
boxBackground.EndContinuousEditingCommand = end;
}
}
private class DelegateCommand : ICommand
{
private readonly Action _execute;
public DelegateCommand(Action execute)
{
_execute = execute;
}
public event EventHandler CanExecuteChanged
{
add => CommandManager.RequerySuggested += value;
remove => CommandManager.RequerySuggested -= value;
}
bool ICommand.CanExecute(object parameter) => true;
void ICommand.Execute(object parameter) => _execute();
}
}
}