in src/Avalonia.Controls.ColorPicker/ColorSpectrum/ColorSpectrum.cs [222:348]
protected override void OnKeyDown(KeyEventArgs e)
{
var key = e.Key;
if (key != Key.Left &&
key != Key.Right &&
key != Key.Up &&
key != Key.Down)
{
base.OnKeyDown(e);
return;
}
bool isControlDown = e.KeyModifiers.HasFlag(KeyModifiers.Control);
HsvComponent incrementComponent = HsvComponent.Hue;
bool isSaturationValue = false;
if (key == Key.Left ||
key == Key.Right)
{
switch (Components)
{
case ColorSpectrumComponents.HueSaturation:
case ColorSpectrumComponents.HueValue:
incrementComponent = HsvComponent.Hue;
break;
case ColorSpectrumComponents.SaturationValue:
isSaturationValue = true;
goto case ColorSpectrumComponents.SaturationHue;
case ColorSpectrumComponents.SaturationHue:
incrementComponent = HsvComponent.Saturation;
break;
case ColorSpectrumComponents.ValueHue:
case ColorSpectrumComponents.ValueSaturation:
incrementComponent = HsvComponent.Value;
break;
}
}
else if (key == Key.Up ||
key == Key.Down)
{
switch (Components)
{
case ColorSpectrumComponents.SaturationHue:
case ColorSpectrumComponents.ValueHue:
incrementComponent = HsvComponent.Hue;
break;
case ColorSpectrumComponents.HueSaturation:
case ColorSpectrumComponents.ValueSaturation:
incrementComponent = HsvComponent.Saturation;
break;
case ColorSpectrumComponents.SaturationValue:
isSaturationValue = true;
goto case ColorSpectrumComponents.HueValue;
case ColorSpectrumComponents.HueValue:
incrementComponent = HsvComponent.Value;
break;
}
}
double minBound = 0.0;
double maxBound = 0.0;
switch (incrementComponent)
{
case HsvComponent.Hue:
minBound = MinHue;
maxBound = MaxHue;
break;
case HsvComponent.Saturation:
minBound = MinSaturation;
maxBound = MaxSaturation;
break;
case HsvComponent.Value:
minBound = MinValue;
maxBound = MaxValue;
break;
}
// The order of saturation and value in the spectrum is reversed - the max value is at the bottom while the min value is at the top -
// so we want left and up to be lower for hue, but higher for saturation and value.
// This will ensure that the icon always moves in the direction of the key press.
IncrementDirection direction =
(incrementComponent == HsvComponent.Hue && (key == Key.Left || key == Key.Up)) ||
(incrementComponent != HsvComponent.Hue && (key == Key.Right || key == Key.Down)) ?
IncrementDirection.Lower :
IncrementDirection.Higher;
// Image is flipped in RightToLeft, so we need to invert direction in that case.
// The combination saturation and value is also flipped, so we need to invert in that case too.
// If both are false, we don't need to invert.
// If both are true, we would invert twice, so not invert at all.
if ((FlowDirection == FlowDirection.RightToLeft) != isSaturationValue &&
(key == Key.Left || key == Key.Right))
{
if (direction == IncrementDirection.Higher)
{
direction = IncrementDirection.Lower;
}
else
{
direction = IncrementDirection.Higher;
}
}
IncrementAmount amount = isControlDown ? IncrementAmount.Large : IncrementAmount.Small;
HsvColor hsvColor = HsvColor;
UpdateColor(ColorPickerHelpers.IncrementColorComponent(
new Hsv(hsvColor),
incrementComponent,
direction,
amount,
shouldWrap: true,
minBound,
maxBound));
e.Handled = true;
}