private void OnColorChanged <T>(AvaloniaPropertyChangedEventArgs <T> args)
        {
            // If we're in the process of internally updating the color, then we don't want to respond to the Color property changing,
            // aside from raising the ColorChanged event.
            if (!m_updatingColor)
            {
                var color = Color;

                m_currentRgb   = new Rgb(color.R / 255.0, color.G / 255.0, color.B / 255.0);
                m_currentAlpha = color.A / 255.0;
                m_currentHsv   = ColorConversion.RgbToHsv(m_currentRgb);
                m_currentHex   = GetCurrentHexValue();

                UpdateColorControls(ColorUpdateReason.ColorPropertyChanged);
            }

            var oldColor = args.OldValue.GetValueOrDefault <Color>();
            var newColor = args.NewValue.GetValueOrDefault <Color>();

            if (oldColor.A != newColor.A ||
                oldColor.R != newColor.R ||
                oldColor.G != newColor.G ||
                oldColor.B != newColor.B)
            {
                var colorChangedEventArgs = new ColorChangedEventArgs(oldColor, newColor);
                ColorChanged?.Invoke(this, colorChangedEventArgs);
            }
        }
        private void OnColorSpectrumColorChanged(object sender, ColorChangedEventArgs args)
        {
            // If we're updating controls, then this is being raised in response to that,
            // so we'll ignore it.
            if (m_updatingControls)
            {
                return;
            }

            var hsvColor = (Hsv)((ColorSpectrum)sender).HsvColor;

            UpdateColor(hsvColor, ColorUpdateReason.ColorSpectrumColorChanged);
        }