1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-12 17:48:31 +00:00

Updated core to correctly use nullable reference types; first changes for new device handling

This commit is contained in:
Darth Affe 2020-12-31 20:07:51 +01:00
parent 5bc945c4f7
commit d4bb0bd9fd
38 changed files with 317 additions and 439 deletions

View File

@ -2,23 +2,6 @@
{ {
public class DefaultColorBehavior : IColorBehavior public class DefaultColorBehavior : IColorBehavior
{ {
#region Properties & Fields
private static DefaultColorBehavior _instance = new DefaultColorBehavior();
/// <summary>
/// Gets the singleton instance of <see cref="DefaultColorBehavior"/>.
/// </summary>
public static DefaultColorBehavior Instance { get; } = _instance;
#endregion
#region Constructors
private DefaultColorBehavior()
{ }
#endregion
#region Methods #region Methods
/// <summary> /// <summary>

View File

@ -4,7 +4,7 @@
{ {
string ToString(Color color); string ToString(Color color);
bool Equals(Color color, object obj); bool Equals(Color color, object? obj);
int GetHashCode(Color color); int GetHashCode(Color color);

View File

@ -7,33 +7,27 @@ using System.Diagnostics;
namespace RGB.NET.Core namespace RGB.NET.Core
{ {
/// <inheritdoc />
/// <summary> /// <summary>
/// Represents an ARGB (alpha, red, green, blue) color. /// Represents an ARGB (alpha, red, green, blue) color.
/// </summary> /// </summary>
[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] [DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")]
public struct Color public readonly struct Color
{ {
#region Constants #region Constants
/// <summary> /// <summary>
/// Gets an transparent color [A: 0, R: 0, G: 0, B: 0] /// Gets an transparent color [A: 0, R: 0, G: 0, B: 0]
/// </summary> /// </summary>
public static Color Transparent => new Color(0, 0, 0, 0); public static Color Transparent => new(0, 0, 0, 0);
#endregion #endregion
#region Properties & Fields #region Properties & Fields
private static IColorBehavior _behavior = DefaultColorBehavior.Instance;
/// <summary> /// <summary>
/// Gets or sets the <see cref="IColorBehavior"/> used to perform operations on colors. /// Gets or sets the <see cref="IColorBehavior"/> used to perform operations on colors.
/// </summary> /// </summary>
public static IColorBehavior Behavior public static IColorBehavior Behavior { get; set; } = new DefaultColorBehavior();
{
get => _behavior;
set => _behavior = value ?? DefaultColorBehavior.Instance;
}
/// <summary> /// <summary>
/// Gets the alpha component value of this <see cref="Color"/> as percentage in the range [0..1]. /// Gets the alpha component value of this <see cref="Color"/> as percentage in the range [0..1].
@ -199,12 +193,13 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="obj">The object to test.</param> /// <param name="obj">The object to test.</param>
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Color" /> equivalent to this <see cref="Color" />; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Color" /> equivalent to this <see cref="Color" />; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) => Behavior.Equals(this, obj); public override bool Equals(object? obj) => Behavior.Equals(this, obj);
/// <summary> /// <summary>
/// Returns a hash code for this <see cref="Color" />, as defined by the current <see cref="Behavior"/>. /// Returns a hash code for this <see cref="Color" />, as defined by the current <see cref="Behavior"/>.
/// </summary> /// </summary>
/// <returns>An integer value that specifies the hash code for this <see cref="Color" />.</returns> /// <returns>An integer value that specifies the hash code for this <see cref="Color" />.</returns>
// ReSharper disable once NonReadonlyMemberInGetHashCode
public override int GetHashCode() => Behavior.GetHashCode(this); public override int GetHashCode() => Behavior.GetHashCode(this);
/// <summary> /// <summary>
@ -246,42 +241,42 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param> /// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
/// <returns>The color.</returns> /// <returns>The color.</returns>
public static implicit operator Color((byte r, byte g, byte b) components) => new Color(components.r, components.g, components.b); public static implicit operator Color((byte r, byte g, byte b) components) => new(components.r, components.g, components.b);
/// <summary> /// <summary>
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>. /// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
/// </summary> /// </summary>
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param> /// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
/// <returns>The color.</returns> /// <returns>The color.</returns>
public static implicit operator Color((byte a, byte r, byte g, byte b) components) => new Color(components.a, components.r, components.g, components.b); public static implicit operator Color((byte a, byte r, byte g, byte b) components) => new(components.a, components.r, components.g, components.b);
/// <summary> /// <summary>
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>. /// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
/// </summary> /// </summary>
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param> /// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
/// <returns>The color.</returns> /// <returns>The color.</returns>
public static implicit operator Color((int r, int g, int b) components) => new Color(components.r, components.g, components.b); public static implicit operator Color((int r, int g, int b) components) => new(components.r, components.g, components.b);
/// <summary> /// <summary>
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>. /// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
/// </summary> /// </summary>
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param> /// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
/// <returns>The color.</returns> /// <returns>The color.</returns>
public static implicit operator Color((int a, int r, int g, int b) components) => new Color(components.a, components.r, components.g, components.b); public static implicit operator Color((int a, int r, int g, int b) components) => new(components.a, components.r, components.g, components.b);
/// <summary> /// <summary>
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>. /// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
/// </summary> /// </summary>
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param> /// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
/// <returns>The color.</returns> /// <returns>The color.</returns>
public static implicit operator Color((double r, double g, double b) components) => new Color(components.r, components.g, components.b); public static implicit operator Color((double r, double g, double b) components) => new(components.r, components.g, components.b);
/// <summary> /// <summary>
/// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>. /// Converts a <see cref="ValueTuple"/> of ARGB-components to a <see cref="Color"/>.
/// </summary> /// </summary>
/// <param name="components">The <see cref="ValueTuple"/> containing the components.</param> /// <param name="components">The <see cref="ValueTuple"/> containing the components.</param>
/// <returns>The color.</returns> /// <returns>The color.</returns>
public static implicit operator Color((double a, double r, double g, double b) components) => new Color(components.a, components.r, components.g, components.b); public static implicit operator Color((double a, double r, double g, double b) components) => new(components.a, components.r, components.g, components.b);
#endregion #endregion
} }

View File

@ -82,7 +82,7 @@ namespace RGB.NET.Core
(double cHue, double cSaturation, double cValue) = color.GetHSV(); (double cHue, double cSaturation, double cValue) = color.GetHSV();
return Create(color.A, cHue * hue, cSaturation * saturation, cValue * value); return Create(color.A, cHue * hue, cSaturation * saturation, cValue * value);
} }
/// <summary> /// <summary>
/// Divides the given HSV values to this color. /// Divides the given HSV values to this color.
/// </summary> /// </summary>
@ -180,7 +180,7 @@ namespace RGB.NET.Core
else // b is max else // b is max
hue = 4.0 + ((r - g) / (max - min)); hue = 4.0 + ((r - g) / (max - min));
hue = hue * 60.0; hue *= 60.0;
hue = hue.Wrap(0, 360); hue = hue.Wrap(0, 360);
double saturation = max.EqualsInTolerance(0) ? 0 : 1.0 - (min / max); double saturation = max.EqualsInTolerance(0) ? 0 : 1.0 - (min / max);
@ -205,21 +205,15 @@ namespace RGB.NET.Core
double q = v * (1.0 - (s * ff)); double q = v * (1.0 - (s * ff));
double t = v * (1.0 - (s * (1.0 - ff))); double t = v * (1.0 - (s * (1.0 - ff)));
switch (i) return i switch
{ {
case 0: 0 => (v, t, p),
return (v, t, p); 1 => (q, v, p),
case 1: 2 => (p, v, t),
return (q, v, p); 3 => (p, q, v),
case 2: 4 => (t, p, v),
return (p, v, t); _ => (v, p, q)
case 3: };
return (p, q, v);
case 4:
return (t, p, v);
default:
return (v, p, q);
}
} }
#endregion #endregion

View File

@ -66,7 +66,7 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to add.</param> /// <param name="b">The blue value to add.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color AddRGB(this Color color, int r = 0, int g = 0, int b = 0) public static Color AddRGB(this Color color, int r = 0, int g = 0, int b = 0)
=> new Color(color.A, color.GetR() + r, color.GetG() + g, color.GetB() + b); => new(color.A, color.GetR() + r, color.GetG() + g, color.GetB() + b);
/// <summary> /// <summary>
/// Adds the given RGB-percent values to this color. /// Adds the given RGB-percent values to this color.
@ -76,7 +76,7 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to add.</param> /// <param name="b">The blue value to add.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color AddRGB(this Color color, double r = 0, double g = 0, double b = 0) public static Color AddRGB(this Color color, double r = 0, double g = 0, double b = 0)
=> new Color(color.A, color.R + r, color.G + g, color.B + b); => new(color.A, color.R + r, color.G + g, color.B + b);
/// <summary> /// <summary>
/// Adds the given alpha value to this color. /// Adds the given alpha value to this color.
@ -84,7 +84,7 @@ namespace RGB.NET.Core
/// <param name="a">The alpha value to add.</param> /// <param name="a">The alpha value to add.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color AddA(this Color color, int a) public static Color AddA(this Color color, int a)
=> new Color(color.GetA() + a, color.R, color.G, color.B); => new(color.GetA() + a, color.R, color.G, color.B);
/// <summary> /// <summary>
/// Adds the given alpha-percent value to this color. /// Adds the given alpha-percent value to this color.
@ -92,7 +92,7 @@ namespace RGB.NET.Core
/// <param name="a">The alpha value to add.</param> /// <param name="a">The alpha value to add.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color AddA(this Color color, double a) public static Color AddA(this Color color, double a)
=> new Color(color.A + a, color.R, color.G, color.B); => new(color.A + a, color.R, color.G, color.B);
#endregion #endregion
@ -106,7 +106,7 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to subtract.</param> /// <param name="b">The blue value to subtract.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SubtractRGB(this Color color, int r = 0, int g = 0, int b = 0) public static Color SubtractRGB(this Color color, int r = 0, int g = 0, int b = 0)
=> new Color(color.A, color.GetR() - r, color.GetG() - g, color.GetB() - b); => new(color.A, color.GetR() - r, color.GetG() - g, color.GetB() - b);
/// <summary> /// <summary>
/// Subtracts the given RGB values to this color. /// Subtracts the given RGB values to this color.
@ -116,7 +116,7 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to subtract.</param> /// <param name="b">The blue value to subtract.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SubtractRGB(this Color color, double r = 0, double g = 0, double b = 0) public static Color SubtractRGB(this Color color, double r = 0, double g = 0, double b = 0)
=> new Color(color.A, color.R - r, color.G - g, color.B - b); => new(color.A, color.R - r, color.G - g, color.B - b);
/// <summary> /// <summary>
/// Subtracts the given alpha value to this color. /// Subtracts the given alpha value to this color.
@ -124,7 +124,7 @@ namespace RGB.NET.Core
/// <param name="a">The alpha value to subtract.</param> /// <param name="a">The alpha value to subtract.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SubtractA(this Color color, int a) public static Color SubtractA(this Color color, int a)
=> new Color(color.GetA() - a, color.R, color.G, color.B); => new(color.GetA() - a, color.R, color.G, color.B);
/// <summary> /// <summary>
/// Subtracts the given alpha-percent value to this color. /// Subtracts the given alpha-percent value to this color.
@ -132,7 +132,7 @@ namespace RGB.NET.Core
/// <param name="a">The alpha value to subtract.</param> /// <param name="a">The alpha value to subtract.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SubtractA(this Color color, double aPercent) public static Color SubtractA(this Color color, double aPercent)
=> new Color(color.A - aPercent, color.R, color.G, color.B); => new(color.A - aPercent, color.R, color.G, color.B);
#endregion #endregion
@ -146,7 +146,7 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to multiply.</param> /// <param name="b">The blue value to multiply.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color MultiplyRGB(this Color color, double r = 1, double g = 1, double b = 1) public static Color MultiplyRGB(this Color color, double r = 1, double g = 1, double b = 1)
=> new Color(color.A, color.R * r, color.G * g, color.B * b); => new(color.A, color.R * r, color.G * g, color.B * b);
/// <summary> /// <summary>
/// Multiplies the given alpha value to this color. /// Multiplies the given alpha value to this color.
@ -154,7 +154,7 @@ namespace RGB.NET.Core
/// <param name="a">The alpha value to multiply.</param> /// <param name="a">The alpha value to multiply.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color MultiplyA(this Color color, double a) public static Color MultiplyA(this Color color, double a)
=> new Color(color.A * a, color.R, color.G, color.B); => new(color.A * a, color.R, color.G, color.B);
#endregion #endregion
@ -168,7 +168,7 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to divide.</param> /// <param name="b">The blue value to divide.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color DivideRGB(this Color color, double r = 1, double g = 1, double b = 1) public static Color DivideRGB(this Color color, double r = 1, double g = 1, double b = 1)
=> new Color(color.A, color.R / r, color.G / g, color.B / b); => new(color.A, color.R / r, color.G / g, color.B / b);
/// <summary> /// <summary>
/// Divides the given alpha value to this color. /// Divides the given alpha value to this color.
@ -176,7 +176,7 @@ namespace RGB.NET.Core
/// <param name="a">The alpha value to divide.</param> /// <param name="a">The alpha value to divide.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color DivideA(this Color color, double a) public static Color DivideA(this Color color, double a)
=> new Color(color.A / a, color.R, color.G, color.B); => new(color.A / a, color.R, color.G, color.B);
#endregion #endregion
@ -190,7 +190,7 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to set.</param> /// <param name="b">The blue value to set.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SetRGB(this Color color, byte? r = null, byte? g = null, byte? b = null) public static Color SetRGB(this Color color, byte? r = null, byte? g = null, byte? b = null)
=> new Color(color.A, r ?? color.GetR(), g ?? color.GetG(), b ?? color.GetB()); => new(color.A, r ?? color.GetR(), g ?? color.GetG(), b ?? color.GetB());
/// <summary> /// <summary>
/// Sets the given RGB value of this color. /// Sets the given RGB value of this color.
@ -200,7 +200,7 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to set.</param> /// <param name="b">The blue value to set.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SetRGB(this Color color, int? r = null, int? g = null, int? b = null) public static Color SetRGB(this Color color, int? r = null, int? g = null, int? b = null)
=> new Color(color.A, r ?? color.GetR(), g ?? color.GetG(), b ?? color.GetB()); => new(color.A, r ?? color.GetR(), g ?? color.GetG(), b ?? color.GetB());
/// <summary> /// <summary>
/// Sets the given RGB value of this color. /// Sets the given RGB value of this color.
@ -210,21 +210,21 @@ namespace RGB.NET.Core
/// <param name="b">The blue value to set.</param> /// <param name="b">The blue value to set.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SetRGB(this Color color, double? r = null, double? g = null, double? b = null) public static Color SetRGB(this Color color, double? r = null, double? g = null, double? b = null)
=> new Color(color.A, r ?? color.R, g ?? color.G, b ?? color.B); => new(color.A, r ?? color.R, g ?? color.G, b ?? color.B);
/// <summary> /// <summary>
/// Sets the given alpha value of this color. /// Sets the given alpha value of this color.
/// </summary> /// </summary>
/// <param name="a">The alpha value to set.</param> /// <param name="a">The alpha value to set.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SetA(this Color color, int a) => new Color(a, color.R, color.G, color.B); public static Color SetA(this Color color, int a) => new(a, color.R, color.G, color.B);
/// <summary> /// <summary>
/// Sets the given alpha value of this color. /// Sets the given alpha value of this color.
/// </summary> /// </summary>
/// <param name="a">The alpha value to set.</param> /// <param name="a">The alpha value to set.</param>
/// <returns>The new color after the modification.</returns> /// <returns>The new color after the modification.</returns>
public static Color SetA(this Color color, double a) => new Color(a, color.R, color.G, color.B); public static Color SetA(this Color color, double a) => new(a, color.R, color.G, color.B);
#endregion #endregion
@ -262,12 +262,12 @@ namespace RGB.NET.Core
hexString = hexString.Substring(1); hexString = hexString.Substring(1);
byte[] data = ConversionHelper.HexToBytes(hexString); byte[] data = ConversionHelper.HexToBytes(hexString);
if (data.Length == 3) return data.Length switch
return new Color(data[0], data[1], data[2]); {
if (data.Length == 4) 3 => new Color(data[0], data[1], data[2]),
return new Color(data[0], data[1], data[2], data[3]); 4 => new Color(data[0], data[1], data[2], data[3]),
_ => throw new ArgumentException($"Invalid hex string '{hexString}'", nameof(hexString))
throw new ArgumentException("Invalid hex string", nameof(hexString)); };
} }
#endregion #endregion

View File

@ -11,7 +11,7 @@ namespace RGB.NET.Core
{ {
#region Properties & Fields #region Properties & Fields
private readonly List<T> _decorators = new List<T>(); private readonly List<T> _decorators = new();
/// <inheritdoc /> /// <inheritdoc />
public IReadOnlyCollection<T> Decorators public IReadOnlyCollection<T> Decorators

View File

@ -21,13 +21,15 @@ namespace RGB.NET.Core
{ {
#region Properties & Fields #region Properties & Fields
RGBSurface? IRGBDevice.Surface { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public abstract TDeviceInfo DeviceInfo { get; } public abstract TDeviceInfo DeviceInfo { get; }
/// <inheritdoc /> /// <inheritdoc />
IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo; IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo;
private Point _location = new Point(0, 0); private Point _location = new(0, 0);
/// <inheritdoc /> /// <inheritdoc />
public Point Location public Point Location
{ {
@ -67,7 +69,7 @@ namespace RGB.NET.Core
private set => SetProperty(ref _deviceRectangle, value); private set => SetProperty(ref _deviceRectangle, value);
} }
private Scale _scale = new Scale(1); private Scale _scale = new(1);
/// <inheritdoc /> /// <inheritdoc />
public Scale Scale public Scale Scale
{ {
@ -79,7 +81,7 @@ namespace RGB.NET.Core
} }
} }
private Rotation _rotation = new Rotation(0); private Rotation _rotation = new(0);
/// <inheritdoc /> /// <inheritdoc />
public Rotation Rotation public Rotation Rotation
{ {
@ -96,13 +98,10 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
protected bool RequiresFlush { get; set; } = false; protected bool RequiresFlush { get; set; } = false;
/// <inheritdoc />
public DeviceUpdateMode UpdateMode { get; set; } = DeviceUpdateMode.Sync;
/// <summary> /// <summary>
/// Gets a dictionary containing all <see cref="Led"/> of the <see cref="IRGBDevice"/>. /// Gets a dictionary containing all <see cref="Led"/> of the <see cref="IRGBDevice"/>.
/// </summary> /// </summary>
protected Dictionary<LedId, Led> LedMapping { get; } = new Dictionary<LedId, Led>(); protected Dictionary<LedId, Led> LedMapping { get; } = new();
#region Indexer #region Indexer
@ -139,8 +138,7 @@ namespace RGB.NET.Core
foreach (Led ledToUpdate in ledsToUpdate) foreach (Led ledToUpdate in ledsToUpdate)
ledToUpdate.Update(); ledToUpdate.Update();
if (UpdateMode.HasFlag(DeviceUpdateMode.Sync)) UpdateLeds(ledsToUpdate);
UpdateLeds(ledsToUpdate);
} }
protected virtual IEnumerable<Led> GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)); protected virtual IEnumerable<Led> GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty));

View File

@ -1,26 +0,0 @@
using System;
namespace RGB.NET.Core
{
/// <summary>
/// Contains a list of different device device update modes.
/// </summary>
[Flags]
public enum DeviceUpdateMode
{
/// <summary>
/// Represents nothing.
/// </summary>
None = 0,
/// <summary>
/// Represents a mode which updates the leds of the device.
/// </summary>
Sync = 1 << 0,
/// <summary>
/// Represents all update modes.
/// </summary>
NoUpdate = 1 << 0xFF
}
}

View File

@ -13,6 +13,8 @@ namespace RGB.NET.Core
{ {
#region Properties #region Properties
RGBSurface? Surface { get; internal set; }
/// <summary> /// <summary>
/// Gets generic information about the <see cref="IRGBDevice"/>. /// Gets generic information about the <see cref="IRGBDevice"/>.
/// </summary> /// </summary>
@ -49,11 +51,6 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
Rotation Rotation { get; set; } Rotation Rotation { get; set; }
/// <summary>
/// Gets or sets the <see cref="DeviceUpdateMode"/> of the <see cref="IRGBDevice"/>.
/// </summary>
DeviceUpdateMode UpdateMode { get; set; }
#endregion #endregion
#region Indexer #region Indexer

View File

@ -33,7 +33,7 @@ namespace RGB.NET.Core
/// Gets the lighting capability of the <see cref="IRGBDevice"/> /// Gets the lighting capability of the <see cref="IRGBDevice"/>
/// </summary> /// </summary>
RGBDeviceLighting Lighting { get; } RGBDeviceLighting Lighting { get; }
/// <summary> /// <summary>
/// Gets the URI of an image of the <see cref="IRGBDevice"/> or null if there is no image. /// Gets the URI of an image of the <see cref="IRGBDevice"/> or null if there is no image.
/// </summary> /// </summary>

View File

@ -20,29 +20,6 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
IEnumerable<IRGBDevice> Devices { get; } IEnumerable<IRGBDevice> Devices { get; }
/// <summary>
/// Gets whether the application has exclusive access to devices or not.
/// </summary>
bool HasExclusiveAccess { get; }
#endregion
#region Methods
/// <summary>
/// Initializes the <see cref="IRGBDeviceProvider"/> if not already happened or reloads it if it is already initialized.
/// </summary>
/// <param name="loadFilter">Specifies which types of devices to load.</param>
/// <param name="exclusiveAccessIfPossible">Specifies whether the application should request exclusive access of possible or not.</param>
/// <param name="throwExceptions">Specifies whether exception during the initialization sequence should be thrown or not.</param>
/// <returns></returns>
bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool exclusiveAccessIfPossible = false, bool throwExceptions = false);
/// <summary>
/// Resets all handled <see cref="IRGBDevice"/> back to default.
/// </summary>
void ResetDevices();
#endregion #endregion
} }
} }

View File

@ -1,20 +0,0 @@
namespace RGB.NET.Core
{
/// <summary>
/// Represents a generic device provider loaded used to dynamically load devices into an application.
/// This class should always provide an empty public constructor!
/// </summary>
public interface IRGBDeviceProviderLoader
{
/// <summary>
/// Indicates if the returned device-provider needs some specific initialization before use.
/// </summary>
bool RequiresInitialization { get; }
/// <summary>
/// Gets the device-provider.
/// </summary>
/// <returns>The device-provider.</returns>
IRGBDeviceProvider GetDeviceProvider();
}
}

View File

@ -8,23 +8,21 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Gets the filename used to resolve the path. /// Gets the filename used to resolve the path.
/// This has to be checked for null since it'S possible that only <see cref="FileName"/> is used.
/// Also check <see cref="RelativePath "/> before use. /// Also check <see cref="RelativePath "/> before use.
/// </summary> /// </summary>
public string RelativePart { get; } public string? RelativePart { get; }
/// <summary> /// <summary>
/// Gets the filename used to resolve the path. /// Gets the filename used to resolve the path.
/// This has to be checked for null since it'S possible that only <see cref="RelativePart"/> is used.
/// Also check <see cref="RelativePath "/> before use. /// Also check <see cref="RelativePath "/> before use.
/// </summary> /// </summary>
public string FileName { get; } public string? FileName { get; }
/// <summary> /// <summary>
/// Gets the relative path used to resolve the path. /// Gets the relative path used to resolve the path.
/// If this is set <see cref="RelativePart" /> and <see cref="FileName" /> are unused. /// If this is set <see cref="RelativePart" /> and <see cref="FileName" /> are unused.
/// </summary> /// </summary>
public string RelativePath { get; } public string? RelativePath { get; }
/// <summary> /// <summary>
/// Gets or sets the resolved path. /// Gets or sets the resolved path.

View File

@ -21,8 +21,8 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Gets the trigger causing this update. /// Gets the trigger causing this update.
/// </summary> /// </summary>
public IUpdateTrigger Trigger { get; } public IUpdateTrigger? Trigger { get; }
/// <summary> /// <summary>
/// Gets the custom-data provided by the trigger for this update. /// Gets the custom-data provided by the trigger for this update.
/// </summary> /// </summary>
@ -39,7 +39,7 @@ namespace RGB.NET.Core
/// <param name="deltaTime">The elapsed time (in seconds) since the last update.</param> /// <param name="deltaTime">The elapsed time (in seconds) since the last update.</param>
/// <param name="trigger">The trigger causing this update.</param> /// <param name="trigger">The trigger causing this update.</param>
/// <param name="customData">The custom-data provided by the trigger for this update.</param> /// <param name="customData">The custom-data provided by the trigger for this update.</param>
public UpdatingEventArgs(double deltaTime, IUpdateTrigger trigger, CustomUpdateData customData) public UpdatingEventArgs(double deltaTime, IUpdateTrigger? trigger, CustomUpdateData customData)
{ {
this.DeltaTime = deltaTime; this.DeltaTime = deltaTime;
this.Trigger = trigger; this.Trigger = trigger;

View File

@ -16,7 +16,7 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="message">The message which describes the reason of throwing this exception.</param> /// <param name="message">The message which describes the reason of throwing this exception.</param>
/// <param name="innerException">Optional inner exception, which lead to this exception.</param> /// <param name="innerException">Optional inner exception, which lead to this exception.</param>
public RGBDeviceException(string message, Exception innerException = null) public RGBDeviceException(string message, Exception? innerException = null)
: base(message, innerException) : base(message, innerException)
{ } { }

View File

@ -0,0 +1,25 @@
using System;
namespace RGB.NET.Core
{
/// <inheritdoc />
/// <summary>
/// Represents an exception thrown by an <see cref="T:RGB.NET.Core.RGBSurface" />.
/// </summary>
public class RGBSurfaceException : ApplicationException
{
#region Constructors
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:RGB.NET.Core.RGBSurfaceException" /> class.
/// </summary>
/// <param name="message">The message which describes the reason of throwing this exception.</param>
/// <param name="innerException">Optional inner exception, which lead to this exception.</param>
public RGBSurfaceException(string message, Exception? innerException = null)
: base(message, innerException)
{ }
#endregion
}
}

View File

@ -12,7 +12,7 @@ namespace RGB.NET.Core
/// <param name="rect">The rectangle to modify.</param> /// <param name="rect">The rectangle to modify.</param>
/// <param name="location">The new location of the rectangle.</param> /// <param name="location">The new location of the rectangle.</param>
/// <returns>The modified <see cref="Rectangle"/>.</returns> /// <returns>The modified <see cref="Rectangle"/>.</returns>
public static Rectangle SetLocation(this Rectangle rect, Point location) => new Rectangle(location, rect.Size); public static Rectangle SetLocation(this Rectangle rect, Point location) => new(location, rect.Size);
/// <summary> /// <summary>
/// Sets the <see cref="Point.X"/> of the <see cref="Rectangle.Location"/> of the given rectangle. /// Sets the <see cref="Point.X"/> of the <see cref="Rectangle.Location"/> of the given rectangle.
@ -20,7 +20,7 @@ namespace RGB.NET.Core
/// <param name="rect">The rectangle to modify.</param> /// <param name="rect">The rectangle to modify.</param>
/// <param name="x">The new x-location of the rectangle.</param> /// <param name="x">The new x-location of the rectangle.</param>
/// <returns>The modified <see cref="Rectangle"/>.</returns> /// <returns>The modified <see cref="Rectangle"/>.</returns>
public static Rectangle SetX(this Rectangle rect, double x) => new Rectangle(new Point(x, rect.Location.Y), rect.Size); public static Rectangle SetX(this Rectangle rect, double x) => new(new Point(x, rect.Location.Y), rect.Size);
/// <summary> /// <summary>
/// Sets the <see cref="Point.Y"/> of the <see cref="Rectangle.Location"/> of the given rectangle. /// Sets the <see cref="Point.Y"/> of the <see cref="Rectangle.Location"/> of the given rectangle.
@ -28,7 +28,7 @@ namespace RGB.NET.Core
/// <param name="rect">The rectangle to modify.</param> /// <param name="rect">The rectangle to modify.</param>
/// <param name="y">The new y-location of the rectangle.</param> /// <param name="y">The new y-location of the rectangle.</param>
/// <returns>The modified <see cref="Rectangle"/>.</returns> /// <returns>The modified <see cref="Rectangle"/>.</returns>
public static Rectangle SetY(this Rectangle rect, double y) => new Rectangle(new Point(rect.Location.X, y), rect.Size); public static Rectangle SetY(this Rectangle rect, double y) => new(new Point(rect.Location.X, y), rect.Size);
/// <summary> /// <summary>
/// Sets the <see cref="Rectangle.Size"/> of the given rectangle. /// Sets the <see cref="Rectangle.Size"/> of the given rectangle.
@ -36,7 +36,7 @@ namespace RGB.NET.Core
/// <param name="rect">The rectangle to modify.</param> /// <param name="rect">The rectangle to modify.</param>
/// <param name="size">The new size of the rectangle.</param> /// <param name="size">The new size of the rectangle.</param>
/// <returns>The modified <see cref="Rectangle"/>.</returns> /// <returns>The modified <see cref="Rectangle"/>.</returns>
public static Rectangle SetSize(this Rectangle rect, Size size) => new Rectangle(rect.Location, size); public static Rectangle SetSize(this Rectangle rect, Size size) => new(rect.Location, size);
/// <summary> /// <summary>
/// Sets the <see cref="Size.Width"/> of the <see cref="Rectangle.Size"/> of the given rectangle. /// Sets the <see cref="Size.Width"/> of the <see cref="Rectangle.Size"/> of the given rectangle.
@ -44,7 +44,7 @@ namespace RGB.NET.Core
/// <param name="rect">The rectangle to modify.</param> /// <param name="rect">The rectangle to modify.</param>
/// <param name="width">The new width of the rectangle.</param> /// <param name="width">The new width of the rectangle.</param>
/// <returns>The modified <see cref="Rectangle"/>.</returns> /// <returns>The modified <see cref="Rectangle"/>.</returns>
public static Rectangle SetWidth(this Rectangle rect, double width) => new Rectangle(rect.Location, new Size(width, rect.Size.Height)); public static Rectangle SetWidth(this Rectangle rect, double width) => new(rect.Location, new Size(width, rect.Size.Height));
/// <summary> /// <summary>
/// Sets the <see cref="Size.Height"/> of the <see cref="Rectangle.Size"/> of the given rectangle. /// Sets the <see cref="Size.Height"/> of the <see cref="Rectangle.Size"/> of the given rectangle.
@ -52,7 +52,7 @@ namespace RGB.NET.Core
/// <param name="rect">The rectangle to modify.</param> /// <param name="rect">The rectangle to modify.</param>
/// <param name="height">The new height of the rectangle.</param> /// <param name="height">The new height of the rectangle.</param>
/// <returns>The modified <see cref="Rectangle"/>.</returns> /// <returns>The modified <see cref="Rectangle"/>.</returns>
public static Rectangle SetHeight(this Rectangle rect, double height) => new Rectangle(rect.Location, new Size(rect.Size.Width, height)); public static Rectangle SetHeight(this Rectangle rect, double height) => new(rect.Location, new Size(rect.Size.Width, height));
/// <summary> /// <summary>
/// Calculates the percentage of intersection of a rectangle. /// Calculates the percentage of intersection of a rectangle.
@ -125,7 +125,7 @@ namespace RGB.NET.Core
/// <param name="x">The x-ammount to move.</param> /// <param name="x">The x-ammount to move.</param>
/// <param name="y">The y-ammount to move.</param> /// <param name="y">The y-ammount to move.</param>
/// <returns>The moved rectangle.</returns> /// <returns>The moved rectangle.</returns>
public static Rectangle Translate(this Rectangle rect, double x = 0, double y = 0) => new Rectangle(rect.Location.Translate(x, y), rect.Size); public static Rectangle Translate(this Rectangle rect, double x = 0, double y = 0) => new(rect.Location.Translate(x, y), rect.Size);
/// <summary> /// <summary>
/// Rotates the specified <see cref="Rectangle"/> by the given amuont around the given origin. /// Rotates the specified <see cref="Rectangle"/> by the given amuont around the given origin.
@ -141,13 +141,13 @@ namespace RGB.NET.Core
/// <param name="rotation">The rotation.</param> /// <param name="rotation">The rotation.</param>
/// <param name="origin">The origin to rotate around. [0,0] if not set.</param> /// <param name="origin">The origin to rotate around. [0,0] if not set.</param>
/// <returns>A array of <see cref="Point"/> containing the new locations of the corners of the original rectangle.</returns> /// <returns>A array of <see cref="Point"/> containing the new locations of the corners of the original rectangle.</returns>
public static Point[] Rotate(this Rectangle rect, Rotation rotation, Point origin = new Point()) public static Point[] Rotate(this Rectangle rect, Rotation rotation, Point origin = new())
{ {
Point[] points = { Point[] points = {
rect.Location, // top left rect.Location, // top left
new Point(rect.Location.X + rect.Size.Width, rect.Location.Y), // top right new(rect.Location.X + rect.Size.Width, rect.Location.Y), // top right
new Point(rect.Location.X + rect.Size.Width, rect.Location.Y + rect.Size.Height), // bottom right new(rect.Location.X + rect.Size.Width, rect.Location.Y + rect.Size.Height), // bottom right
new Point(rect.Location.X, rect.Location.Y + rect.Size.Height), // bottom right new(rect.Location.X, rect.Location.Y + rect.Size.Height), // bottom right
}; };
double sin = Math.Sin(rotation.Radians); double sin = Math.Sin(rotation.Radians);

View File

@ -14,7 +14,7 @@ namespace RGB.NET.Core
public RGBSurface? Surface { get; private set; } public RGBSurface? Surface { get; private set; }
/// <inheritdoc /> /// <inheritdoc />
public IBrush Brush { get; set; } public IBrush? Brush { get; set; }
/// <inheritdoc /> /// <inheritdoc />
public int ZIndex { get; set; } = 0; public int ZIndex { get; set; } = 0;
@ -39,16 +39,10 @@ namespace RGB.NET.Core
public abstract IList<Led> GetLeds(); public abstract IList<Led> GetLeds();
/// <inheritdoc /> /// <inheritdoc />
public virtual void OnAttach(RGBSurface surface) public virtual void OnAttach(RGBSurface surface) => Surface = surface;
{
Surface = surface;
}
/// <inheritdoc /> /// <inheritdoc />
public virtual void OnDetach(RGBSurface surface) public virtual void OnDetach(RGBSurface surface) => Surface = null;
{
Surface = null;
}
#endregion #endregion
} }

View File

@ -16,7 +16,7 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Gets or sets the <see cref="IBrush"/> which should be drawn over this <see cref="ILedGroup"/>. /// Gets or sets the <see cref="IBrush"/> which should be drawn over this <see cref="ILedGroup"/>.
/// </summary> /// </summary>
IBrush Brush { get; set; } IBrush? Brush { get; set; }
/// <summary> /// <summary>
/// Gets or sets the z-index of this <see cref="ILedGroup"/> to allow ordering them before drawing. (lowest first) (default: 0) /// Gets or sets the z-index of this <see cref="ILedGroup"/> to allow ordering them before drawing. (lowest first) (default: 0)

View File

@ -1,4 +1,6 @@
namespace RGB.NET.Core using System;
namespace RGB.NET.Core
{ {
/// <summary> /// <summary>
/// Contains helper methods for converting things. /// Contains helper methods for converting things.
@ -20,10 +22,10 @@
for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx) for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{ {
byte b = ((byte)(bytes[bx] >> 4)); byte b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b + 0x37: b + 0x30); c[cx] = (char)(b > 9 ? b + 0x37 : b + 0x30);
b = ((byte)(bytes[bx] & 0x0F)); b = ((byte)(bytes[bx] & 0x0F));
c[++cx] = (char)(b > 9 ? b + 0x37: b + 0x30); c[++cx] = (char)(b > 9 ? b + 0x37 : b + 0x30);
} }
return new string(c); return new string(c);
@ -38,7 +40,7 @@
public static byte[] HexToBytes(string hexString) public static byte[] HexToBytes(string hexString)
{ {
if ((hexString.Length == 0) || ((hexString.Length % 2) != 0)) if ((hexString.Length == 0) || ((hexString.Length % 2) != 0))
return new byte[0]; return Array.Empty<byte>();
byte[] buffer = new byte[hexString.Length / 2]; byte[] buffer = new byte[hexString.Length / 2];
for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx) for (int bx = 0, sx = 0; bx < buffer.Length; ++bx, ++sx)

View File

@ -14,7 +14,7 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Occurs when a path is resolving. /// Occurs when a path is resolving.
/// </summary> /// </summary>
public static event EventHandler<ResolvePathEventArgs> ResolvingAbsolutePath; public static event EventHandler<ResolvePathEventArgs>? ResolvingAbsolutePath;
#endregion #endregion
@ -25,7 +25,7 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="relativePath">The relative part of the path to convert.</param> /// <param name="relativePath">The relative part of the path to convert.</param>
/// <returns>The absolute path.</returns> /// <returns>The absolute path.</returns>
public static string GetAbsolutePath(string relativePath) => GetAbsolutePath((object)null, relativePath); public static string GetAbsolutePath(string relativePath) => GetAbsolutePath((object?)null, relativePath);
/// <summary> /// <summary>
/// Returns an absolute path created from an relative path relatvie to the location of the executung assembly. /// Returns an absolute path created from an relative path relatvie to the location of the executung assembly.
@ -42,17 +42,17 @@ namespace RGB.NET.Core
/// <param name="relativePath">The relative path to convert.</param> /// <param name="relativePath">The relative path to convert.</param>
/// <param name="fileName">The file name of the path to convert.</param> /// <param name="fileName">The file name of the path to convert.</param>
/// <returns>The absolute path.</returns> /// <returns>The absolute path.</returns>
public static string GetAbsolutePath(object sender, string relativePath, string fileName) public static string GetAbsolutePath(object? sender, string relativePath, string fileName)
{ {
string relativePart = Path.Combine(relativePath, fileName); string relativePart = Path.Combine(relativePath, fileName);
string assemblyLocation = Assembly.GetEntryAssembly()?.Location; string? assemblyLocation = Assembly.GetEntryAssembly()?.Location;
if (assemblyLocation == null) return relativePart; if (assemblyLocation == null) return relativePart;
string directoryName = Path.GetDirectoryName(assemblyLocation); string? directoryName = Path.GetDirectoryName(assemblyLocation);
string path = directoryName == null ? null : Path.Combine(directoryName, relativePart); string path = directoryName == null ? string.Empty : Path.Combine(directoryName, relativePart);
ResolvePathEventArgs args = new ResolvePathEventArgs(relativePath, fileName, path); ResolvePathEventArgs args = new(relativePath, fileName, path);
ResolvingAbsolutePath?.Invoke(sender, args); ResolvingAbsolutePath?.Invoke(sender, args);
return args.FinalPath; return args.FinalPath;
@ -64,15 +64,15 @@ namespace RGB.NET.Core
/// <param name="sender">The requester of this path. (Used for better control when using the event to override this behavior.)</param> /// <param name="sender">The requester of this path. (Used for better control when using the event to override this behavior.)</param>
/// <param name="relativePath">The relative path to convert.</param> /// <param name="relativePath">The relative path to convert.</param>
/// <returns>The absolute path.</returns> /// <returns>The absolute path.</returns>
public static string GetAbsolutePath(object sender, string relativePath) public static string GetAbsolutePath(object? sender, string relativePath)
{ {
string assemblyLocation = Assembly.GetEntryAssembly()?.Location; string? assemblyLocation = Assembly.GetEntryAssembly()?.Location;
if (assemblyLocation == null) return relativePath; if (assemblyLocation == null) return relativePath;
string directoryName = Path.GetDirectoryName(assemblyLocation); string? directoryName = Path.GetDirectoryName(assemblyLocation);
string path = directoryName == null ? null : Path.Combine(directoryName, relativePath); string path = directoryName == null ? string.Empty : Path.Combine(directoryName, relativePath);
ResolvePathEventArgs args = new ResolvePathEventArgs(relativePath, path); ResolvePathEventArgs args = new(relativePath, path);
ResolvingAbsolutePath?.Invoke(sender, args); ResolvingAbsolutePath?.Invoke(sender, args);
return args.FinalPath; return args.FinalPath;

View File

@ -35,11 +35,11 @@ namespace RGB.NET.Core
set => SetProperty(ref _shape, value); set => SetProperty(ref _shape, value);
} }
private string _shapeData; private string? _shapeData;
/// <summary> /// <summary>
/// Gets or sets the data used for by the <see cref="Core.Shape.Custom"/>-<see cref="Core.Shape"/>. /// Gets or sets the data used for by the <see cref="Core.Shape.Custom"/>-<see cref="Core.Shape"/>.
/// </summary> /// </summary>
public string ShapeData public string? ShapeData
{ {
get => _shapeData; get => _shapeData;
set => SetProperty(ref _shapeData, value); set => SetProperty(ref _shapeData, value);
@ -155,7 +155,7 @@ namespace RGB.NET.Core
if (!IsLocked) if (!IsLocked)
{ {
if (RequestedColor.HasValue) if (RequestedColor.HasValue)
RequestedColor += value; RequestedColor = RequestedColor.Value + value;
else else
RequestedColor = value; RequestedColor = value;
} }
@ -185,12 +185,12 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Gets the URI of an image of the <see cref="Led"/> or null if there is no image. /// Gets the URI of an image of the <see cref="Led"/> or null if there is no image.
/// </summary> /// </summary>
public Uri Image { get; set; } public Uri? Image { get; set; }
/// <summary> /// <summary>
/// Gets the provider-specific data associated with this led. /// Gets the provider-specific data associated with this led.
/// </summary> /// </summary>
public object CustomData { get; } public object? CustomData { get; }
#endregion #endregion
@ -204,7 +204,7 @@ namespace RGB.NET.Core
/// <param name="location">The physical location of the <see cref="Led"/> relative to the <see cref="Device"/>.</param> /// <param name="location">The physical location of the <see cref="Led"/> relative to the <see cref="Device"/>.</param>
/// <param name="size">The size of the <see cref="Led"/>.</param> /// <param name="size">The size of the <see cref="Led"/>.</param>
/// <param name="customData">The provider-specific data associated with this led.</param> /// <param name="customData">The provider-specific data associated with this led.</param>
internal Led(IRGBDevice device, LedId id, Point location, Size size, object customData = null) internal Led(IRGBDevice device, LedId id, Point location, Size size, object? customData = null)
{ {
this.Device = device; this.Device = device;
this.Id = id; this.Id = id;
@ -219,14 +219,18 @@ namespace RGB.NET.Core
#region Methods #region Methods
private void DevicePropertyChanged(object sender, PropertyChangedEventArgs e) private void DevicePropertyChanged(object? sender, PropertyChangedEventArgs e)
{ {
if ((e.PropertyName == nameof(IRGBDevice.Location))) switch (e.PropertyName)
UpdateAbsoluteData();
else if (e.PropertyName == nameof(IRGBDevice.DeviceRectangle))
{ {
UpdateActualData(); case nameof(IRGBDevice.Location):
UpdateAbsoluteData(); UpdateAbsoluteData();
break;
case nameof(IRGBDevice.DeviceRectangle):
UpdateActualData();
UpdateAbsoluteData();
break;
} }
} }
@ -235,13 +239,13 @@ namespace RGB.NET.Core
ActualSize = Size * Device.Scale; ActualSize = Size * Device.Scale;
Point actualLocation = (Location * Device.Scale); Point actualLocation = (Location * Device.Scale);
Rectangle ledRectangle = new Rectangle(Location * Device.Scale, Size * Device.Scale); Rectangle ledRectangle = new(Location * Device.Scale, Size * Device.Scale);
if (Device.Rotation.IsRotated) if (Device.Rotation.IsRotated)
{ {
Point deviceCenter = new Rectangle(Device.ActualSize).Center; Point deviceCenter = new Rectangle(Device.ActualSize).Center;
Point actualDeviceCenter = new Rectangle(Device.DeviceRectangle.Size).Center; Point actualDeviceCenter = new Rectangle(Device.DeviceRectangle.Size).Center;
Point centerOffset = new Point(actualDeviceCenter.X - deviceCenter.X, actualDeviceCenter.Y - deviceCenter.Y); Point centerOffset = new(actualDeviceCenter.X - deviceCenter.X, actualDeviceCenter.Y - deviceCenter.Y);
actualLocation = actualLocation.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center) + centerOffset; actualLocation = actualLocation.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center) + centerOffset;
ledRectangle = new Rectangle(ledRectangle.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center)).Translate(centerOffset); ledRectangle = new Rectangle(ledRectangle.Rotate(Device.Rotation, new Rectangle(Device.ActualSize).Center)).Translate(centerOffset);

View File

@ -14,7 +14,7 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Occurs when a property value changes. /// Occurs when a property value changes.
/// </summary> /// </summary>
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler? PropertyChanged;
#endregion #endregion
@ -28,10 +28,7 @@ namespace RGB.NET.Core
/// <param name="value">Value to apply.</param> /// <param name="value">Value to apply.</param>
/// <returns></returns> /// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual bool RequiresUpdate<T>(ref T storage, T value) protected virtual bool RequiresUpdate<T>(ref T storage, T value) => !Equals(storage, value);
{
return !Equals(storage, value);
}
/// <summary> /// <summary>
/// Checks if the property already matches the desired value and updates it if not. /// Checks if the property already matches the desired value and updates it if not.
@ -42,13 +39,13 @@ namespace RGB.NET.Core
/// <param name="propertyName">Name of the property used to notify listeners. This value is optional /// <param name="propertyName">Name of the property used to notify listeners. This value is optional
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute"/>.</param> /// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute"/>.</param>
/// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns> /// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns>
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string? propertyName = null)
{ {
if (!this.RequiresUpdate(ref storage, value)) return false; if (!RequiresUpdate(ref storage, value)) return false;
storage = value; storage = value;
// ReSharper disable once ExplicitCallerInfoArgument // ReSharper disable once ExplicitCallerInfoArgument
this.OnPropertyChanged(propertyName); OnPropertyChanged(propertyName);
return true; return true;
} }
@ -57,10 +54,8 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="propertyName">Name of the property used to notify listeners. This value is optional /// <param name="propertyName">Name of the property used to notify listeners. This value is optional
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute"/>.</param> /// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute"/>.</param>
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{ => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion #endregion
} }

View File

@ -9,14 +9,14 @@ namespace RGB.NET.Core
/// Represents a point consisting of a X- and a Y-position. /// Represents a point consisting of a X- and a Y-position.
/// </summary> /// </summary>
[DebuggerDisplay("[X: {X}, Y: {Y}]")] [DebuggerDisplay("[X: {X}, Y: {Y}]")]
public struct Point public readonly struct Point
{ {
#region Constants #region Constants
/// <summary> /// <summary>
/// Gets a [NaN,NaN]-Point. /// Gets a [NaN,NaN]-Point.
/// </summary> /// </summary>
public static Point Invalid => new Point(double.NaN, double.NaN); public static Point Invalid => new(double.NaN, double.NaN);
#endregion #endregion
@ -62,13 +62,13 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="obj">The object to test.</param> /// <param name="obj">The object to test.</param>
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Point" /> equivalent to this <see cref="Point" />; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Point" /> equivalent to this <see cref="Point" />; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) public override bool Equals(object? obj)
{ {
if (!(obj is Point)) return false; if (!(obj is Point)) return false;
Point comparePoint = (Point)obj; Point comparePoint = (Point)obj;
return ((double.IsNaN(X) && double.IsNaN(comparePoint.X)) || X.EqualsInTolerance(comparePoint.X)) return ((double.IsNaN(X) && double.IsNaN(comparePoint.X)) || X.EqualsInTolerance(comparePoint.X))
&& ((double.IsNaN(Y) && double.IsNaN(comparePoint.Y)) || Y.EqualsInTolerance(comparePoint.Y)); && ((double.IsNaN(Y) && double.IsNaN(comparePoint.Y)) || Y.EqualsInTolerance(comparePoint.Y));
} }
/// <summary> /// <summary>
@ -111,7 +111,7 @@ namespace RGB.NET.Core
/// <param name="point1">The first <see cref="Point"/>.</param> /// <param name="point1">The first <see cref="Point"/>.</param>
/// <param name="point2">The second <see cref="Point"/>.</param> /// <param name="point2">The second <see cref="Point"/>.</param>
/// <returns>A new <see cref="Point"/> representing the addition of the two provided <see cref="Point"/>.</returns> /// <returns>A new <see cref="Point"/> representing the addition of the two provided <see cref="Point"/>.</returns>
public static Point operator +(Point point1, Point point2) => new Point(point1.X + point2.X, point1.Y + point2.Y); public static Point operator +(Point point1, Point point2) => new(point1.X + point2.X, point1.Y + point2.Y);
/// <summary> /// <summary>
/// Returns a new <see cref="Rectangle"/> created from the provided <see cref="Point"/> and <see cref="Size"/>. /// Returns a new <see cref="Rectangle"/> created from the provided <see cref="Point"/> and <see cref="Size"/>.
@ -119,7 +119,7 @@ namespace RGB.NET.Core
/// <param name="point">The <see cref="Point"/> of the rectangle.</param> /// <param name="point">The <see cref="Point"/> of the rectangle.</param>
/// <param name="size">The <see cref="Size"/> of the rectangle.</param> /// <param name="size">The <see cref="Size"/> of the rectangle.</param>
/// <returns>The rectangle created from the provided <see cref="Point"/> and <see cref="Size"/>.</returns> /// <returns>The rectangle created from the provided <see cref="Point"/> and <see cref="Size"/>.</returns>
public static Rectangle operator +(Point point, Size size) => new Rectangle(point, size); public static Rectangle operator +(Point point, Size size) => new(point, size);
/// <summary> /// <summary>
/// Returns a new <see cref="Point"/> representing the subtraction of the two provided <see cref="Point"/>. /// Returns a new <see cref="Point"/> representing the subtraction of the two provided <see cref="Point"/>.
@ -127,7 +127,7 @@ namespace RGB.NET.Core
/// <param name="point1">The first <see cref="Point"/>.</param> /// <param name="point1">The first <see cref="Point"/>.</param>
/// <param name="point2">The second <see cref="Point"/>.</param> /// <param name="point2">The second <see cref="Point"/>.</param>
/// <returns>A new <see cref="Point"/> representing the subtraction of the two provided <see cref="Point"/>.</returns> /// <returns>A new <see cref="Point"/> representing the subtraction of the two provided <see cref="Point"/>.</returns>
public static Point operator -(Point point1, Point point2) => new Point(point1.X - point2.X, point1.Y - point2.Y); public static Point operator -(Point point1, Point point2) => new(point1.X - point2.X, point1.Y - point2.Y);
/// <summary> /// <summary>
/// Returns a new <see cref="Point"/> representing the multiplication of the two provided <see cref="Point"/>. /// Returns a new <see cref="Point"/> representing the multiplication of the two provided <see cref="Point"/>.
@ -135,7 +135,7 @@ namespace RGB.NET.Core
/// <param name="point1">The first <see cref="Point"/>.</param> /// <param name="point1">The first <see cref="Point"/>.</param>
/// <param name="point2">The second <see cref="Point"/>.</param> /// <param name="point2">The second <see cref="Point"/>.</param>
/// <returns>A new <see cref="Point"/> representing the multiplication of the two provided <see cref="Point"/>.</returns> /// <returns>A new <see cref="Point"/> representing the multiplication of the two provided <see cref="Point"/>.</returns>
public static Point operator *(Point point1, Point point2) => new Point(point1.X * point2.X, point1.Y * point2.Y); public static Point operator *(Point point1, Point point2) => new(point1.X * point2.X, point1.Y * point2.Y);
/// <summary> /// <summary>
/// Returns a new <see cref="Point"/> representing the division of the two provided <see cref="Point"/>. /// Returns a new <see cref="Point"/> representing the division of the two provided <see cref="Point"/>.
@ -155,7 +155,7 @@ namespace RGB.NET.Core
/// <param name="point">The <see cref="Point"/>.</param> /// <param name="point">The <see cref="Point"/>.</param>
/// <param name="scale">The <see cref="Scale"/>.</param> /// <param name="scale">The <see cref="Scale"/>.</param>
/// <returns>A new <see cref="Point"/> representing the multiplication of the <see cref="Point"/> and the provided <see cref="Scale"/>.</returns> /// <returns>A new <see cref="Point"/> representing the multiplication of the <see cref="Point"/> and the provided <see cref="Scale"/>.</returns>
public static Point operator *(Point point, Scale scale) => new Point(point.X * scale.Horizontal, point.Y * scale.Vertical); public static Point operator *(Point point, Scale scale) => new(point.X * scale.Horizontal, point.Y * scale.Vertical);
#endregion #endregion
} }

View File

@ -12,7 +12,7 @@ namespace RGB.NET.Core
/// Represents a rectangle defined by it's position and it's size. /// Represents a rectangle defined by it's position and it's size.
/// </summary> /// </summary>
[DebuggerDisplay("[Location: {Location}, Size: {Size}]")] [DebuggerDisplay("[Location: {Location}, Size: {Size}]")]
public struct Rectangle public readonly struct Rectangle
{ {
#region Properties & Fields #region Properties & Fields
@ -69,6 +69,7 @@ namespace RGB.NET.Core
{ {
this.Location = location; this.Location = location;
this.Size = size; this.Size = size;
Center = new Point(Location.X + (Size.Width / 2.0), Location.Y + (Size.Height / 2.0)); Center = new Point(Location.X + (Size.Width / 2.0), Location.Y + (Size.Height / 2.0));
} }
@ -95,15 +96,14 @@ namespace RGB.NET.Core
double posX2 = double.MinValue; double posX2 = double.MinValue;
double posY2 = double.MinValue; double posY2 = double.MinValue;
if (rectangles != null) foreach (Rectangle rectangle in rectangles)
foreach (Rectangle rectangle in rectangles) {
{ hasPoint = true;
hasPoint = true; posX = Math.Min(posX, rectangle.Location.X);
posX = Math.Min(posX, rectangle.Location.X); posY = Math.Min(posY, rectangle.Location.Y);
posY = Math.Min(posY, rectangle.Location.Y); posX2 = Math.Max(posX2, rectangle.Location.X + rectangle.Size.Width);
posX2 = Math.Max(posX2, rectangle.Location.X + rectangle.Size.Width); posY2 = Math.Max(posY2, rectangle.Location.Y + rectangle.Size.Height);
posY2 = Math.Max(posY2, rectangle.Location.Y + rectangle.Size.Height); }
}
(Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0)); (Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0));
Location = location; Location = location;
@ -136,15 +136,14 @@ namespace RGB.NET.Core
double posX2 = double.MinValue; double posX2 = double.MinValue;
double posY2 = double.MinValue; double posY2 = double.MinValue;
if (points != null) foreach (Point point in points)
foreach (Point point in points) {
{ hasPoint = true;
hasPoint = true; posX = Math.Min(posX, point.X);
posX = Math.Min(posX, point.X); posY = Math.Min(posY, point.Y);
posY = Math.Min(posY, point.Y); posX2 = Math.Max(posX2, point.X);
posX2 = Math.Max(posX2, point.X); posY2 = Math.Max(posY2, point.Y);
posY2 = Math.Max(posY2, point.Y); }
}
(Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0)); (Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0));
@ -178,7 +177,7 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="obj">The object to test.</param> /// <param name="obj">The object to test.</param>
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Rectangle" /> equivalent to this <see cref="Rectangle" />; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Rectangle" /> equivalent to this <see cref="Rectangle" />; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) public override bool Equals(object? obj)
{ {
if (!(obj is Rectangle compareRect)) if (!(obj is Rectangle compareRect))
return false; return false;

View File

@ -10,7 +10,7 @@ namespace RGB.NET.Core
/// Represents an angular rotation. /// Represents an angular rotation.
/// </summary> /// </summary>
[DebuggerDisplay("[{Degrees}°]")] [DebuggerDisplay("[{Degrees}°]")]
public struct Rotation public readonly struct Rotation
{ {
#region Constants #region Constants
@ -64,14 +64,14 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="degrees">The angle in degrees.</param> /// <param name="degrees">The angle in degrees.</param>
/// <returns>The new rotation.</returns> /// <returns>The new rotation.</returns>
public static Rotation FromDegrees(double degrees) => new Rotation(degrees); public static Rotation FromDegrees(double degrees) => new(degrees);
/// <summary> /// <summary>
/// Creates a new Rotation out of the given radian-angle. /// Creates a new Rotation out of the given radian-angle.
/// </summary> /// </summary>
/// <param name="degrees">The angle in radians.</param> /// <param name="degrees">The angle in radians.</param>
/// <returns>The new rotation.</returns> /// <returns>The new rotation.</returns>
public static Rotation FromRadians(double radians) => new Rotation(radians * RADIANS_DEGREES_CONVERSION, radians); public static Rotation FromRadians(double radians) => new(radians * RADIANS_DEGREES_CONVERSION, radians);
/// <summary> /// <summary>
/// Tests whether the specified <see cref="Rotation" /> is equivalent to this <see cref="Rotation" />. /// Tests whether the specified <see cref="Rotation" /> is equivalent to this <see cref="Rotation" />.
@ -85,7 +85,7 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="obj">The object to test.</param> /// <param name="obj">The object to test.</param>
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Rotation" /> equivalent to this <see cref="Rotation" />; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Rotation" /> equivalent to this <see cref="Rotation" />; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) => obj is Rotation other && Equals(other); public override bool Equals(object? obj) => obj is Rotation other && Equals(other);
/// <summary> /// <summary>
/// Returns a hash code for this <see cref="Rotation" />. /// Returns a hash code for this <see cref="Rotation" />.
@ -119,7 +119,7 @@ namespace RGB.NET.Core
/// <param name="rotation">The <see cref="Rotation"/>.</param> /// <param name="rotation">The <see cref="Rotation"/>.</param>
/// <param name="value">The value to add.</param> /// <param name="value">The value to add.</param>
/// <returns>A new <see cref="Rotation"/> representing the addition of the <see cref="Rotation"/> and the provided value.</returns> /// <returns>A new <see cref="Rotation"/> representing the addition of the <see cref="Rotation"/> and the provided value.</returns>
public static Rotation operator +(Rotation rotation, double value) => new Rotation(rotation.Degrees + value); public static Rotation operator +(Rotation rotation, double value) => new(rotation.Degrees + value);
/// <summary> /// <summary>
/// Returns a new <see cref="Rotation"/> representing the subtraction of the <see cref="Rotation"/> and the provided value. /// Returns a new <see cref="Rotation"/> representing the subtraction of the <see cref="Rotation"/> and the provided value.
@ -127,7 +127,7 @@ namespace RGB.NET.Core
/// <param name="rotation">The <see cref="Rotation"/>.</param> /// <param name="rotation">The <see cref="Rotation"/>.</param>
/// <param name="value">The value to substract.</param> /// <param name="value">The value to substract.</param>
/// <returns>A new <see cref="Rotation"/> representing the subtraction of the <see cref="Rotation"/> and the provided value.</returns> /// <returns>A new <see cref="Rotation"/> representing the subtraction of the <see cref="Rotation"/> and the provided value.</returns>
public static Rotation operator -(Rotation rotation, double value) => new Rotation(rotation.Degrees - value); public static Rotation operator -(Rotation rotation, double value) => new(rotation.Degrees - value);
/// <summary> /// <summary>
/// Returns a new <see cref="Rotation"/> representing the multiplication of the <see cref="Rotation"/> and the provided value. /// Returns a new <see cref="Rotation"/> representing the multiplication of the <see cref="Rotation"/> and the provided value.
@ -135,7 +135,7 @@ namespace RGB.NET.Core
/// <param name="rotation">The <see cref="Rotation"/>.</param> /// <param name="rotation">The <see cref="Rotation"/>.</param>
/// <param name="value">The value to multiply with.</param> /// <param name="value">The value to multiply with.</param>
/// <returns>A new <see cref="Rotation"/> representing the multiplication of the <see cref="Rotation"/> and the provided value.</returns> /// <returns>A new <see cref="Rotation"/> representing the multiplication of the <see cref="Rotation"/> and the provided value.</returns>
public static Rotation operator *(Rotation rotation, double value) => new Rotation(rotation.Degrees * value); public static Rotation operator *(Rotation rotation, double value) => new(rotation.Degrees * value);
/// <summary> /// <summary>
/// Returns a new <see cref="Rotation"/> representing the division of the <see cref="Rotation"/> and the provided value. /// Returns a new <see cref="Rotation"/> representing the division of the <see cref="Rotation"/> and the provided value.
@ -149,7 +149,7 @@ namespace RGB.NET.Core
/// Converts a double to a <see cref="Rotation" />. /// Converts a double to a <see cref="Rotation" />.
/// </summary> /// </summary>
/// <param name="rotation">The rotation in degrees to convert.</param> /// <param name="rotation">The rotation in degrees to convert.</param>
public static implicit operator Rotation(double rotation) => new Rotation(rotation); public static implicit operator Rotation(double rotation) => new(rotation);
/// <summary> /// <summary>
/// Converts <see cref="Rotation" /> to a double representing the rotation in degrees. /// Converts <see cref="Rotation" /> to a double representing the rotation in degrees.

View File

@ -9,7 +9,7 @@ namespace RGB.NET.Core
/// Represents a scaling. /// Represents a scaling.
/// </summary> /// </summary>
[DebuggerDisplay("[Horizontal: {Horizontal}, Vertical: {Vertical}]")] [DebuggerDisplay("[Horizontal: {Horizontal}, Vertical: {Vertical}]")]
public struct Scale public readonly struct Scale
{ {
#region Properties & Fields #region Properties & Fields
@ -61,7 +61,7 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="obj">The object to test.</param> /// <param name="obj">The object to test.</param>
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Scale" /> equivalent to this <see cref="Scale" />; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Scale" /> equivalent to this <see cref="Scale" />; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) => obj is Scale other && Equals(other); public override bool Equals(object? obj) => obj is Scale other && Equals(other);
/// <summary> /// <summary>
/// Returns a hash code for this <see cref="Scale" />. /// Returns a hash code for this <see cref="Scale" />.
@ -106,7 +106,7 @@ namespace RGB.NET.Core
/// <param name="scale">The <see cref="Scale"/>.</param> /// <param name="scale">The <see cref="Scale"/>.</param>
/// <param name="value">The value to add.</param> /// <param name="value">The value to add.</param>
/// <returns>A new <see cref="Scale"/> representing the addition of the <see cref="Scale"/> and the provided value.</returns> /// <returns>A new <see cref="Scale"/> representing the addition of the <see cref="Scale"/> and the provided value.</returns>
public static Scale operator +(Scale scale, double value) => new Scale(scale.Horizontal + value, scale.Vertical + value); public static Scale operator +(Scale scale, double value) => new(scale.Horizontal + value, scale.Vertical + value);
/// <summary> /// <summary>
/// Returns a new <see cref="Scale"/> representing the subtraction of the <see cref="Scale"/> and the provided value. /// Returns a new <see cref="Scale"/> representing the subtraction of the <see cref="Scale"/> and the provided value.
@ -114,7 +114,7 @@ namespace RGB.NET.Core
/// <param name="scale">The <see cref="Scale"/>.</param> /// <param name="scale">The <see cref="Scale"/>.</param>
/// <param name="value">The value to substract.</param> /// <param name="value">The value to substract.</param>
/// <returns>A new <see cref="Scale"/> representing the subtraction of the <see cref="Scale"/> and the provided value.</returns> /// <returns>A new <see cref="Scale"/> representing the subtraction of the <see cref="Scale"/> and the provided value.</returns>
public static Scale operator -(Scale scale, double value) => new Scale(scale.Horizontal - value, scale.Vertical - value); public static Scale operator -(Scale scale, double value) => new(scale.Horizontal - value, scale.Vertical - value);
/// <summary> /// <summary>
/// Returns a new <see cref="Scale"/> representing the multiplication of the <see cref="Scale"/> and the provided value. /// Returns a new <see cref="Scale"/> representing the multiplication of the <see cref="Scale"/> and the provided value.
@ -122,7 +122,7 @@ namespace RGB.NET.Core
/// <param name="scale">The <see cref="Scale"/>.</param> /// <param name="scale">The <see cref="Scale"/>.</param>
/// <param name="value">The value to multiply with.</param> /// <param name="value">The value to multiply with.</param>
/// <returns>A new <see cref="Scale"/> representing the multiplication of the <see cref="Scale"/> and the provided value.</returns> /// <returns>A new <see cref="Scale"/> representing the multiplication of the <see cref="Scale"/> and the provided value.</returns>
public static Scale operator *(Scale scale, double value) => new Scale(scale.Horizontal * value, scale.Vertical * value); public static Scale operator *(Scale scale, double value) => new(scale.Horizontal * value, scale.Vertical * value);
/// <summary> /// <summary>
/// Returns a new <see cref="Scale"/> representing the division of the <see cref="Scale"/> and the provided value. /// Returns a new <see cref="Scale"/> representing the division of the <see cref="Scale"/> and the provided value.
@ -137,7 +137,7 @@ namespace RGB.NET.Core
/// Converts a double to a <see cref="Scale" />. /// Converts a double to a <see cref="Scale" />.
/// </summary> /// </summary>
/// <param name="scale">The scale value to convert.</param> /// <param name="scale">The scale value to convert.</param>
public static implicit operator Scale(double scale) => new Scale(scale); public static implicit operator Scale(double scale) => new(scale);
#endregion #endregion
} }

View File

@ -9,14 +9,14 @@ namespace RGB.NET.Core
/// Represents a size consisting of a width and a height. /// Represents a size consisting of a width and a height.
/// </summary> /// </summary>
[DebuggerDisplay("[Width: {Width}, Height: {Height}]")] [DebuggerDisplay("[Width: {Width}, Height: {Height}]")]
public struct Size public readonly struct Size
{ {
#region Constants #region Constants
/// <summary> /// <summary>
/// Gets a [NaN,NaN]-Size. /// Gets a [NaN,NaN]-Size.
/// </summary> /// </summary>
public static Size Invalid => new Size(double.NaN, double.NaN); public static Size Invalid => new(double.NaN, double.NaN);
#endregion #endregion
@ -71,13 +71,13 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="obj">The object to test.</param> /// <param name="obj">The object to test.</param>
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Size" /> equivalent to this <see cref="Size" />; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Size" /> equivalent to this <see cref="Size" />; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj) public override bool Equals(object? obj)
{ {
if (!(obj is Size)) return false; if (!(obj is Size size)) return false;
Size compareSize = (Size)obj; (double width, double height) = size;
return ((double.IsNaN(Width) && double.IsNaN(compareSize.Width)) || Width.EqualsInTolerance(compareSize.Width)) return ((double.IsNaN(Width) && double.IsNaN(width)) || Width.EqualsInTolerance(width))
&& ((double.IsNaN(Height) && double.IsNaN(compareSize.Height)) || Height.EqualsInTolerance(compareSize.Height)); && ((double.IsNaN(Height) && double.IsNaN(height)) || Height.EqualsInTolerance(height));
} }
/// <summary> /// <summary>
@ -131,7 +131,7 @@ namespace RGB.NET.Core
/// <param name="size1">The first <see cref="Size"/>.</param> /// <param name="size1">The first <see cref="Size"/>.</param>
/// <param name="size2">The second <see cref="Size"/>.</param> /// <param name="size2">The second <see cref="Size"/>.</param>
/// <returns>A new <see cref="Size"/> representing the addition of the two provided <see cref="Size"/>.</returns> /// <returns>A new <see cref="Size"/> representing the addition of the two provided <see cref="Size"/>.</returns>
public static Size operator +(Size size1, Size size2) => new Size(size1.Width + size2.Width, size1.Height + size2.Height); public static Size operator +(Size size1, Size size2) => new(size1.Width + size2.Width, size1.Height + size2.Height);
/// <summary> /// <summary>
/// Returns a new <see cref="Rectangle"/> created from the provided <see cref="Point"/> and <see cref="Size"/>. /// Returns a new <see cref="Rectangle"/> created from the provided <see cref="Point"/> and <see cref="Size"/>.
@ -139,7 +139,7 @@ namespace RGB.NET.Core
/// <param name="size">The <see cref="Size"/> of the rectangle.</param> /// <param name="size">The <see cref="Size"/> of the rectangle.</param>
/// <param name="point">The <see cref="Point"/> of the rectangle.</param> /// <param name="point">The <see cref="Point"/> of the rectangle.</param>
/// <returns>The rectangle created from the provided <see cref="Point"/> and <see cref="Size"/>.</returns> /// <returns>The rectangle created from the provided <see cref="Point"/> and <see cref="Size"/>.</returns>
public static Rectangle operator +(Size size, Point point) => new Rectangle(point, size); public static Rectangle operator +(Size size, Point point) => new(point, size);
/// <summary> /// <summary>
/// Returns a new <see cref="Size"/> representing the subtraction of the two provided <see cref="Size"/>. /// Returns a new <see cref="Size"/> representing the subtraction of the two provided <see cref="Size"/>.
@ -147,7 +147,7 @@ namespace RGB.NET.Core
/// <param name="size1">The first <see cref="Size"/>.</param> /// <param name="size1">The first <see cref="Size"/>.</param>
/// <param name="size2">The second <see cref="Size"/>.</param> /// <param name="size2">The second <see cref="Size"/>.</param>
/// <returns>A new <see cref="Size"/> representing the subtraction of the two provided <see cref="Size"/>.</returns> /// <returns>A new <see cref="Size"/> representing the subtraction of the two provided <see cref="Size"/>.</returns>
public static Size operator -(Size size1, Size size2) => new Size(size1.Width - size2.Width, size1.Height - size2.Height); public static Size operator -(Size size1, Size size2) => new(size1.Width - size2.Width, size1.Height - size2.Height);
/// <summary> /// <summary>
/// Returns a new <see cref="Size"/> representing the multiplication of the two provided <see cref="Size"/>. /// Returns a new <see cref="Size"/> representing the multiplication of the two provided <see cref="Size"/>.
@ -155,7 +155,7 @@ namespace RGB.NET.Core
/// <param name="size1">The first <see cref="Size"/>.</param> /// <param name="size1">The first <see cref="Size"/>.</param>
/// <param name="size2">The second <see cref="Size"/>.</param> /// <param name="size2">The second <see cref="Size"/>.</param>
/// <returns>A new <see cref="Size"/> representing the multiplication of the two provided <see cref="Size"/>.</returns> /// <returns>A new <see cref="Size"/> representing the multiplication of the two provided <see cref="Size"/>.</returns>
public static Size operator *(Size size1, Size size2) => new Size(size1.Width * size2.Width, size1.Height * size2.Height); public static Size operator *(Size size1, Size size2) => new(size1.Width * size2.Width, size1.Height * size2.Height);
/// <summary> /// <summary>
/// Returns a new <see cref="Size"/> representing the multiplication of the <see cref="Size"/> and the provided factor. /// Returns a new <see cref="Size"/> representing the multiplication of the <see cref="Size"/> and the provided factor.
@ -163,7 +163,7 @@ namespace RGB.NET.Core
/// <param name="size">The <see cref="Size"/>.</param> /// <param name="size">The <see cref="Size"/>.</param>
/// <param name="factor">The factor by which the <see cref="Size"/> should be multiplied.</param> /// <param name="factor">The factor by which the <see cref="Size"/> should be multiplied.</param>
/// <returns>A new <see cref="Size"/> representing the multiplication of the <see cref="Size"/> and the provided factor.</returns> /// <returns>A new <see cref="Size"/> representing the multiplication of the <see cref="Size"/> and the provided factor.</returns>
public static Size operator *(Size size, double factor) => new Size(size.Width * factor, size.Height * factor); public static Size operator *(Size size, double factor) => new(size.Width * factor, size.Height * factor);
/// <summary> /// <summary>
/// Returns a new <see cref="Size"/> representing the division of the two provided <see cref="Size"/>. /// Returns a new <see cref="Size"/> representing the division of the two provided <see cref="Size"/>.
@ -189,7 +189,7 @@ namespace RGB.NET.Core
/// <param name="size">The <see cref="Size"/> to scale.</param> /// <param name="size">The <see cref="Size"/> to scale.</param>
/// <param name="scale">The scaling factor.</param> /// <param name="scale">The scaling factor.</param>
/// <returns>A new <see cref="Size"/> representing the multiplication of the <see cref="Size"/> and the given <see cref="Scale"/>.</returns> /// <returns>A new <see cref="Size"/> representing the multiplication of the <see cref="Size"/> and the given <see cref="Scale"/>.</returns>
public static Size operator *(Size size, Scale scale) => new Size(size.Width * scale.Horizontal, size.Height * scale.Vertical); public static Size operator *(Size size, Scale scale) => new(size.Width * scale.Horizontal, size.Height * scale.Vertical);
#endregion #endregion
} }

View File

@ -21,13 +21,12 @@ namespace RGB.NET.Core
private Stopwatch _deltaTimeCounter; private Stopwatch _deltaTimeCounter;
private IList<IRGBDeviceProvider> _deviceProvider = new List<IRGBDeviceProvider>();
private IList<IRGBDevice> _devices = new List<IRGBDevice>(); private IList<IRGBDevice> _devices = new List<IRGBDevice>();
private IList<IUpdateTrigger> _updateTriggers = new List<IUpdateTrigger>(); private IList<IUpdateTrigger> _updateTriggers = new List<IUpdateTrigger>();
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
private readonly LinkedList<ILedGroup> _ledGroups = new LinkedList<ILedGroup>(); private readonly LinkedList<ILedGroup> _ledGroups = new();
// ReSharper restore InconsistentNaming // ReSharper restore InconsistentNaming
@ -102,22 +101,22 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Occurs when a catched exception is thrown inside the <see cref="RGBSurface"/>. /// Occurs when a catched exception is thrown inside the <see cref="RGBSurface"/>.
/// </summary> /// </summary>
public event ExceptionEventHandler Exception; public event ExceptionEventHandler? Exception;
/// <summary> /// <summary>
/// Occurs when the <see cref="RGBSurface"/> starts updating. /// Occurs when the <see cref="RGBSurface"/> starts updating.
/// </summary> /// </summary>
public event UpdatingEventHandler Updating; public event UpdatingEventHandler? Updating;
/// <summary> /// <summary>
/// Occurs when the <see cref="RGBSurface"/> update is done. /// Occurs when the <see cref="RGBSurface"/> update is done.
/// </summary> /// </summary>
public event UpdatedEventHandler Updated; public event UpdatedEventHandler? Updated;
/// <summary> /// <summary>
/// Occurs when the layout of this <see cref="RGBSurface"/> changed. /// Occurs when the layout of this <see cref="RGBSurface"/> changed.
/// </summary> /// </summary>
public event SurfaceLayoutChangedEventHandler SurfaceLayoutChanged; public event SurfaceLayoutChangedEventHandler? SurfaceLayoutChanged;
// ReSharper restore EventNeverSubscribedTo.Global // ReSharper restore EventNeverSubscribedTo.Global
@ -143,13 +142,10 @@ namespace RGB.NET.Core
/// <param name="flushLeds">Specifies whether all <see cref="Led"/>, (including clean ones) should be updated.</param> /// <param name="flushLeds">Specifies whether all <see cref="Led"/>, (including clean ones) should be updated.</param>
public void Update(bool flushLeds = false) => Update(null, new CustomUpdateData(("flushLeds", flushLeds))); public void Update(bool flushLeds = false) => Update(null, new CustomUpdateData(("flushLeds", flushLeds)));
private void Update(object updateTrigger, CustomUpdateData customData) => Update(updateTrigger as IUpdateTrigger, customData); private void Update(object? updateTrigger, CustomUpdateData customData) => Update(updateTrigger as IUpdateTrigger, customData);
private void Update(IUpdateTrigger updateTrigger, CustomUpdateData customData) private void Update(IUpdateTrigger? updateTrigger, CustomUpdateData customData)
{ {
if (customData == null)
customData = new CustomUpdateData();
try try
{ {
bool flushLeds = customData["flushLeds"] as bool? ?? false; bool flushLeds = customData["flushLeds"] as bool? ?? false;
@ -172,9 +168,8 @@ namespace RGB.NET.Core
if (updateDevices) if (updateDevices)
foreach (IRGBDevice device in _devices) foreach (IRGBDevice device in _devices)
if (!device.UpdateMode.HasFlag(DeviceUpdateMode.NoUpdate)) try { device.Update(flushLeds); }
try { device.Update(flushLeds); } catch (Exception ex) { OnException(ex); }
catch (Exception ex) { OnException(ex); }
OnUpdated(); OnUpdated();
} }
@ -188,23 +183,19 @@ namespace RGB.NET.Core
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public void Dispose()
{ {
List<IRGBDevice> devices;
lock (_devices) lock (_devices)
foreach (IRGBDevice device in _devices) devices = new List<IRGBDevice>(_devices);
try { device.Dispose(); }
catch { /* We do what we can */}
lock (_deviceProvider) foreach (IRGBDevice device in devices)
foreach (IRGBDeviceProvider deviceProvider in _deviceProvider) try { Detach(device); }
try { deviceProvider.Dispose(); } catch { /* We do what we can */}
catch { /* We do what we can */}
foreach (IUpdateTrigger updateTrigger in _updateTriggers) foreach (IUpdateTrigger updateTrigger in _updateTriggers)
try { updateTrigger.Dispose(); } try { updateTrigger.Dispose(); }
catch { /* We do what we can */} catch { /* We do what we can */}
_ledGroups.Clear(); _ledGroups.Clear();
_devices = null;
_deviceProvider = null;
} }
/// <summary> /// <summary>
@ -214,15 +205,15 @@ namespace RGB.NET.Core
private void Render(ILedGroup ledGroup) private void Render(ILedGroup ledGroup)
{ {
IList<Led> leds = ledGroup.GetLeds().ToList(); IList<Led> leds = ledGroup.GetLeds().ToList();
IBrush brush = ledGroup.Brush; IBrush? brush = ledGroup.Brush;
if ((brush == null) || !brush.IsEnabled) return; if ((brush == null) || !brush.IsEnabled) return;
switch (brush.BrushCalculationMode) switch (brush.BrushCalculationMode)
{ {
case BrushCalculationMode.Relative: case BrushCalculationMode.Relative:
Rectangle brushRectangle = new Rectangle(leds.Select(led => led.AbsoluteLedRectangle)); Rectangle brushRectangle = new(leds.Select(led => led.AbsoluteLedRectangle));
Point offset = new Point(-brushRectangle.Location.X, -brushRectangle.Location.Y); Point offset = new(-brushRectangle.Location.X, -brushRectangle.Location.Y);
brushRectangle = brushRectangle.SetLocation(new Point(0, 0)); brushRectangle = brushRectangle.SetLocation(new Point(0, 0));
brush.PerformRender(brushRectangle, leds.Select(led => new BrushRenderTarget(led, led.AbsoluteLedRectangle.Translate(offset)))); brush.PerformRender(brushRectangle, leds.Select(led => new BrushRenderTarget(led, led.AbsoluteLedRectangle.Translate(offset))));
break; break;
@ -247,8 +238,6 @@ namespace RGB.NET.Core
/// <returns><c>true</c> if the <see cref="ILedGroup"/> could be attached; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if the <see cref="ILedGroup"/> could be attached; otherwise, <c>false</c>.</returns>
public bool AttachLedGroup(ILedGroup ledGroup) public bool AttachLedGroup(ILedGroup ledGroup)
{ {
if (ledGroup == null) return false;
lock (_ledGroups) lock (_ledGroups)
{ {
if (_ledGroups.Contains(ledGroup)) return false; if (_ledGroups.Contains(ledGroup)) return false;
@ -267,11 +256,9 @@ namespace RGB.NET.Core
/// <returns><c>true</c> if the <see cref="ILedGroup"/> could be detached; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if the <see cref="ILedGroup"/> could be detached; otherwise, <c>false</c>.</returns>
public bool DetachLedGroup(ILedGroup ledGroup) public bool DetachLedGroup(ILedGroup ledGroup)
{ {
if (ledGroup == null) return false;
lock (_ledGroups) lock (_ledGroups)
{ {
LinkedListNode<ILedGroup> node = _ledGroups.Find(ledGroup); LinkedListNode<ILedGroup>? node = _ledGroups.Find(ledGroup);
if (node == null) return false; if (node == null) return false;
_ledGroups.Remove(node); _ledGroups.Remove(node);
@ -280,52 +267,46 @@ namespace RGB.NET.Core
return true; return true;
} }
} }
// ReSharper disable UnusedMember.Global
/// <summary>
/// Loads all devices the given by the <see cref="IRGBDeviceProvider"/> provided by the give <see cref="IRGBDeviceProviderLoader"/>.
/// </summary>
/// <param name="deviceProviderLoader">The <see cref="IRGBDeviceProviderLoader"/> which provides the <see cref="IRGBDeviceProvider"/> to load the devices from.</param>
/// <param name="loadFilter">Specifies which types of devices to load.</param>
/// <param name="exclusiveAccessIfPossible">Specifies whether the application should request exclusive access of possible or not.</param>
/// <param name="throwExceptions">Specifies whether exception during the initialization sequence should be thrown or not.</param>
public void LoadDevices(IRGBDeviceProviderLoader deviceProviderLoader, RGBDeviceType loadFilter = RGBDeviceType.All,
bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
=> LoadDevices(deviceProviderLoader.GetDeviceProvider(), loadFilter, exclusiveAccessIfPossible, throwExceptions);
/// <summary> public void Attach(IEnumerable<IRGBDevice> devices)
/// Loads all devices the given <see cref="IRGBDeviceProvider"/> is able to provide.
/// </summary>
/// <param name="deviceProvider">The <see cref="IRGBDeviceProvider"/> to load the devices from.</param>
/// <param name="loadFilter">Specifies which types of devices to load.</param>
/// <param name="exclusiveAccessIfPossible">Specifies whether the application should request exclusive access of possible or not.</param>
/// <param name="throwExceptions">Specifies whether exception during the initialization sequence should be thrown or not.</param>
public void LoadDevices(IRGBDeviceProvider deviceProvider, RGBDeviceType loadFilter = RGBDeviceType.All, bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
{ {
lock (_deviceProvider) lock (_devices)
{ {
if (_deviceProvider.Contains(deviceProvider) || _deviceProvider.Any(x => x.GetType() == deviceProvider.GetType())) return; foreach (IRGBDevice device in devices)
Attach(device);
}
}
List<IRGBDevice> addedDevices = new List<IRGBDevice>(); public void Attach(IRGBDevice device)
if (deviceProvider.IsInitialized || deviceProvider.Initialize(loadFilter, exclusiveAccessIfPossible, throwExceptions)) {
{ lock (_devices)
_deviceProvider.Add(deviceProvider); {
lock (_devices) if (_devices.Contains(device)) throw new RGBSurfaceException($"The device '{device.DeviceInfo.Manufacturer} {device.DeviceInfo.Model}' is already attached.");
foreach (IRGBDevice device in deviceProvider.Devices)
{
if (_devices.Contains(device)) continue;
addedDevices.Add(device); device.Surface = this;
device.PropertyChanged += DeviceOnPropertyChanged; _devices.Add(device);
_devices.Add(device); }
} }
}
if (addedDevices.Any()) public void Detach(IEnumerable<IRGBDevice> devices)
{ {
UpdateSurfaceRectangle(); lock (_devices)
SurfaceLayoutChanged?.Invoke(new SurfaceLayoutChangedEventArgs(addedDevices, true, false)); {
} foreach (IRGBDevice device in devices)
Detach(device);
}
}
public void Detach(IRGBDevice device)
{
lock (_devices)
{
if (!_devices.Contains(device)) throw new RGBSurfaceException($"The device '{device.DeviceInfo.Manufacturer} {device.DeviceInfo.Model}' isn't attached.");
device.Surface = null;
_devices.Remove(device);
} }
} }
@ -347,14 +328,14 @@ namespace RGB.NET.Core
private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs) private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{ {
UpdateSurfaceRectangle(); UpdateSurfaceRectangle();
SurfaceLayoutChanged?.Invoke(new SurfaceLayoutChangedEventArgs(new[] { sender as IRGBDevice }, false, true)); SurfaceLayoutChanged?.Invoke(new SurfaceLayoutChangedEventArgs((sender is IRGBDevice device) ? new[] { device } : Array.Empty<IRGBDevice>(), false, true));
} }
private void UpdateSurfaceRectangle() private void UpdateSurfaceRectangle()
{ {
lock (_devices) lock (_devices)
{ {
Rectangle devicesRectangle = new Rectangle(_devices.Select(d => d.DeviceRectangle)); Rectangle devicesRectangle = new(_devices.Select(d => d.DeviceRectangle));
SurfaceRectangle = SurfaceRectangle.SetSize(new Size(devicesRectangle.Location.X + devicesRectangle.Size.Width, devicesRectangle.Location.Y + devicesRectangle.Size.Height)); SurfaceRectangle = SurfaceRectangle.SetSize(new Size(devicesRectangle.Location.X + devicesRectangle.Size.Width, devicesRectangle.Location.Y + devicesRectangle.Size.Height));
} }
} }
@ -368,7 +349,7 @@ namespace RGB.NET.Core
where T : class where T : class
{ {
lock (_devices) lock (_devices)
return new ReadOnlyCollection<T>(_devices.Select(x => x as T).Where(x => x != null).ToList()); return new ReadOnlyCollection<T>(_devices.Where(x => x is T).Cast<T>().ToList());
} }
/// <summary> /// <summary>
@ -421,7 +402,7 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Handles the needed event-calls before updating. /// Handles the needed event-calls before updating.
/// </summary> /// </summary>
private void OnUpdating(IUpdateTrigger trigger, CustomUpdateData customData) private void OnUpdating(IUpdateTrigger? trigger, CustomUpdateData customData)
{ {
try try
{ {

View File

@ -10,9 +10,9 @@ namespace RGB.NET.Core
#region Events #region Events
/// <inheritdoc /> /// <inheritdoc />
public event EventHandler<CustomUpdateData> Starting; public event EventHandler<CustomUpdateData>? Starting;
/// <inheritdoc /> /// <inheritdoc />
public event EventHandler<CustomUpdateData> Update; public event EventHandler<CustomUpdateData>? Update;
#endregion #endregion
@ -22,13 +22,13 @@ namespace RGB.NET.Core
/// Invokes the <see cref="Starting"/>-event. /// Invokes the <see cref="Starting"/>-event.
/// </summary> /// </summary>
/// <param name="updateData">Optional custom-data passed to the subscribers of the <see cref="Starting"/>.event.</param> /// <param name="updateData">Optional custom-data passed to the subscribers of the <see cref="Starting"/>.event.</param>
protected virtual void OnStartup(CustomUpdateData updateData = null) => Starting?.Invoke(this, updateData); protected virtual void OnStartup(CustomUpdateData? updateData = null) => Starting?.Invoke(this, updateData ?? new CustomUpdateData());
/// <summary> /// <summary>
/// Invokes the <see cref="Update"/>-event. /// Invokes the <see cref="Update"/>-event.
/// </summary> /// </summary>
/// <param name="updateData">Optional custom-data passed to the subscribers of the <see cref="Update"/>.event.</param> /// <param name="updateData">Optional custom-data passed to the subscribers of the <see cref="Update"/>.event.</param>
protected virtual void OnUpdate(CustomUpdateData updateData = null) => Update?.Invoke(this, updateData); protected virtual void OnUpdate(CustomUpdateData? updateData = null) => Update?.Invoke(this, updateData ?? new CustomUpdateData());
/// <inheritdoc /> /// <inheritdoc />
public abstract void Dispose(); public abstract void Dispose();

View File

@ -9,7 +9,7 @@ namespace RGB.NET.Core
{ {
#region Properties & Fields #region Properties & Fields
private Dictionary<string, object> _data = new Dictionary<string, object>(); private Dictionary<string, object?> _data = new();
#endregion #endregion
@ -20,10 +20,10 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="key">The key of the value.</param> /// <param name="key">The key of the value.</param>
/// <returns>The value represented by the given key.</returns> /// <returns>The value represented by the given key.</returns>
public object this[string key] public object? this[string key]
{ {
get => _data.TryGetValue(key?.ToUpperInvariant() ?? string.Empty, out object data) ? data : default; get => _data.TryGetValue(key.ToUpperInvariant(), out object? data) ? data : default;
set => _data[key?.ToUpperInvariant() ?? string.Empty] = value; set => _data[key.ToUpperInvariant()] = value;
} }
#endregion #endregion

View File

@ -53,12 +53,12 @@ namespace RGB.NET.Core
} }
} }
protected AutoResetEvent HasDataEvent = new AutoResetEvent(false); protected AutoResetEvent HasDataEvent { get; set; } = new(false);
protected bool IsRunning; protected bool IsRunning { get; set; }
protected Task UpdateTask; protected Task? UpdateTask { get; set; }
protected CancellationTokenSource UpdateTokenSource; protected CancellationTokenSource? UpdateTokenSource { get; set; }
protected CancellationToken UpdateToken; protected CancellationToken UpdateToken { get; set; }
#endregion #endregion
@ -106,15 +106,18 @@ namespace RGB.NET.Core
IsRunning = false; IsRunning = false;
UpdateTokenSource.Cancel(); UpdateTokenSource?.Cancel();
await UpdateTask; if (UpdateTask != null)
UpdateTask.Dispose(); await UpdateTask;
UpdateTask?.Dispose();
UpdateTask = null; UpdateTask = null;
} }
protected virtual void UpdateLoop() protected virtual void UpdateLoop()
{ {
OnStartup(); OnStartup();
while (!UpdateToken.IsCancellationRequested) while (!UpdateToken.IsCancellationRequested)
{ {
if (HasDataEvent.WaitOne(Timeout)) if (HasDataEvent.WaitOne(Timeout))

View File

@ -10,12 +10,13 @@ namespace RGB.NET.Core
/// <typeparam name="TIdentifier">The type of the key used to identify some data.</typeparam> /// <typeparam name="TIdentifier">The type of the key used to identify some data.</typeparam>
/// <typeparam name="TData">The type of the data.</typeparam> /// <typeparam name="TData">The type of the data.</typeparam>
public abstract class UpdateQueue<TIdentifier, TData> : IDisposable public abstract class UpdateQueue<TIdentifier, TData> : IDisposable
where TIdentifier : notnull
{ {
#region Properties & Fields #region Properties & Fields
private readonly object _dataLock = new object(); private readonly object _dataLock = new object();
private readonly IDeviceUpdateTrigger _updateTrigger; private readonly IDeviceUpdateTrigger _updateTrigger;
private Dictionary<TIdentifier, TData> _currentDataSet; private Dictionary<TIdentifier, TData>? _currentDataSet;
#endregion #endregion
@ -42,16 +43,18 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="sender">The <see cref="IUpdateTrigger"/> causing this update.</param> /// <param name="sender">The <see cref="IUpdateTrigger"/> causing this update.</param>
/// <param name="customData"><see cref="CustomUpdateData"/> provided by the trigger.</param> /// <param name="customData"><see cref="CustomUpdateData"/> provided by the trigger.</param>
protected virtual void OnUpdate(object sender, CustomUpdateData customData) protected virtual void OnUpdate(object? sender, CustomUpdateData customData)
{ {
Dictionary<TIdentifier, TData> dataSet; Dictionary<TIdentifier, TData> dataSet;
lock (_dataLock) lock (_dataLock)
{ {
if (_currentDataSet == null) return;
dataSet = _currentDataSet; dataSet = _currentDataSet;
_currentDataSet = null; _currentDataSet = null;
} }
if ((dataSet != null) && (dataSet.Count != 0)) if (dataSet.Count != 0)
Update(dataSet); Update(dataSet);
} }
@ -60,7 +63,7 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <param name="sender">The starting <see cref="IUpdateTrigger"/>.</param> /// <param name="sender">The starting <see cref="IUpdateTrigger"/>.</param>
/// <param name="customData"><see cref="CustomUpdateData"/> provided by the trigger.</param> /// <param name="customData"><see cref="CustomUpdateData"/> provided by the trigger.</param>
protected virtual void OnStartup(object sender, CustomUpdateData customData) { } protected virtual void OnStartup(object? sender, CustomUpdateData customData) { }
/// <summary> /// <summary>
/// Performs the update this queue is responsible for. /// Performs the update this queue is responsible for.
@ -75,7 +78,7 @@ namespace RGB.NET.Core
// ReSharper disable once MemberCanBeProtected.Global // ReSharper disable once MemberCanBeProtected.Global
public virtual void SetData(Dictionary<TIdentifier, TData> dataSet) public virtual void SetData(Dictionary<TIdentifier, TData> dataSet)
{ {
if ((dataSet == null) || (dataSet.Count == 0)) return; if (dataSet.Count == 0) return;
lock (_dataLock) lock (_dataLock)
{ {
@ -83,8 +86,8 @@ namespace RGB.NET.Core
_currentDataSet = dataSet; _currentDataSet = dataSet;
else else
{ {
foreach (KeyValuePair<TIdentifier, TData> command in dataSet) foreach ((TIdentifier key, TData value) in dataSet)
_currentDataSet[command.Key] = command.Value; _currentDataSet[key] = value;
} }
} }
@ -132,7 +135,7 @@ namespace RGB.NET.Core
/// Calls <see cref="UpdateQueue{TIdentifier,TData}.SetData"/> for a data set created out of the provided list of <see cref="Led"/>. /// Calls <see cref="UpdateQueue{TIdentifier,TData}.SetData"/> for a data set created out of the provided list of <see cref="Led"/>.
/// </summary> /// </summary>
/// <param name="leds"></param> /// <param name="leds"></param>
public void SetData(IEnumerable<Led> leds) => SetData(leds?.ToDictionary(x => x.CustomData ?? x.Id, x => x.Color)); public void SetData(IEnumerable<Led> leds) => SetData(leds.ToDictionary(x => x.CustomData ?? x.Id, x => x.Color));
#endregion #endregion
} }

View File

@ -10,11 +10,11 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Occurs when the trigger is starting up. /// Occurs when the trigger is starting up.
/// </summary> /// </summary>
event EventHandler<CustomUpdateData> Starting; event EventHandler<CustomUpdateData>? Starting;
/// <summary> /// <summary>
/// Occurs when the trigger wants to cause an update. /// Occurs when the trigger wants to cause an update.
/// </summary> /// </summary>
event EventHandler<CustomUpdateData> Update; event EventHandler<CustomUpdateData>? Update;
} }
} }

View File

@ -14,12 +14,11 @@ namespace RGB.NET.Core
{ {
#region Properties & Fields #region Properties & Fields
private object _lock = new object(); private object _lock = new();
private CancellationTokenSource _updateTokenSource; protected Task? UpdateTask { get; set; }
private CancellationToken _updateToken; protected CancellationTokenSource? UpdateTokenSource { get; set; }
private Task _updateTask; protected CancellationToken UpdateToken { get; set; }
private Stopwatch _sleepCounter;
private double _updateFrequency = 1.0 / 30.0; private double _updateFrequency = 1.0 / 30.0;
/// <summary> /// <summary>
@ -46,8 +45,6 @@ namespace RGB.NET.Core
/// <param name="autostart">A value indicating if the trigger should automatically <see cref="Start"/> right after construction.</param> /// <param name="autostart">A value indicating if the trigger should automatically <see cref="Start"/> right after construction.</param>
public TimerUpdateTrigger(bool autostart = true) public TimerUpdateTrigger(bool autostart = true)
{ {
_sleepCounter = new Stopwatch();
if (autostart) if (autostart)
Start(); Start();
} }
@ -63,11 +60,11 @@ namespace RGB.NET.Core
{ {
lock (_lock) lock (_lock)
{ {
if (_updateTask == null) if (UpdateTask == null)
{ {
_updateTokenSource?.Dispose(); UpdateTokenSource?.Dispose();
_updateTokenSource = new CancellationTokenSource(); UpdateTokenSource = new CancellationTokenSource();
_updateTask = Task.Factory.StartNew(UpdateLoop, (_updateToken = _updateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default); UpdateTask = Task.Factory.StartNew(UpdateLoop, (UpdateToken = UpdateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default);
} }
} }
} }
@ -79,30 +76,35 @@ namespace RGB.NET.Core
{ {
lock (_lock) lock (_lock)
{ {
if (_updateTask != null) if (UpdateTask != null)
{ {
_updateTokenSource.Cancel(); UpdateTokenSource?.Cancel();
// ReSharper disable once MethodSupportsCancellation // ReSharper disable once MethodSupportsCancellation
_updateTask.Wait(); UpdateTask.Wait();
_updateTask.Dispose(); UpdateTask.Dispose();
_updateTask = null; UpdateTask = null;
} }
} }
} }
private void UpdateLoop() private void UpdateLoop()
{ {
while (!_updateToken.IsCancellationRequested) OnStartup();
while (!UpdateToken.IsCancellationRequested)
{ {
_sleepCounter.Restart(); long preUpdateTicks = Stopwatch.GetTimestamp();
OnUpdate(); OnUpdate();
_sleepCounter.Stop(); if (UpdateFrequency > 0)
LastUpdateTime = _sleepCounter.Elapsed.TotalSeconds; {
int sleep = (int)((UpdateFrequency * 1000.0) - _sleepCounter.ElapsedMilliseconds); double lastUpdateTime = ((Stopwatch.GetTimestamp() - preUpdateTicks) / 10000.0);
if (sleep > 0) LastUpdateTime = lastUpdateTime;
Thread.Sleep(sleep); int sleep = (int)((UpdateFrequency * 1000.0) - lastUpdateTime);
if (sleep > 0)
Thread.Sleep(sleep);
}
} }
} }

View File

@ -1,24 +0,0 @@
using RGB.NET.Core;
namespace RGB.NET.Devices.Corsair
{
/// <summary>
/// Represents a device provider loaded used to dynamically load corsair devices into an application.
/// </summary>
public class CorsairDeviceProviderLoader : IRGBDeviceProviderLoader
{
#region Properties & Fields
/// <inheritdoc />
public bool RequiresInitialization => false;
#endregion
#region Methods
/// <inheritdoc />
public IRGBDeviceProvider GetDeviceProvider() => CorsairDeviceProvider.Instance;
#endregion
}
}

View File

@ -31,7 +31,7 @@ namespace RGB.NET.Groups
public ListLedGroup(RGBSurface? surface) public ListLedGroup(RGBSurface? surface)
: base(surface) : base(surface)
{ } { }
/// <inheritdoc /> /// <inheritdoc />
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="T:RGB.NET.Groups.ListLedGroup" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Groups.ListLedGroup" /> class.
@ -72,8 +72,6 @@ namespace RGB.NET.Groups
/// <param name="leds">The <see cref="Led"/> to add.</param> /// <param name="leds">The <see cref="Led"/> to add.</param>
public void AddLeds(IEnumerable<Led> leds) public void AddLeds(IEnumerable<Led> leds)
{ {
if (leds == null) return;
lock (GroupLeds) lock (GroupLeds)
foreach (Led led in leds) foreach (Led led in leds)
if ((led != null) && !ContainsLed(led)) if ((led != null) && !ContainsLed(led))
@ -92,8 +90,6 @@ namespace RGB.NET.Groups
/// <param name="leds">The <see cref="Led"/> to remove.</param> /// <param name="leds">The <see cref="Led"/> to remove.</param>
public void RemoveLeds(IEnumerable<Led> leds) public void RemoveLeds(IEnumerable<Led> leds)
{ {
if (leds == null) return;
lock (GroupLeds) lock (GroupLeds)
foreach (Led led in leds) foreach (Led led in leds)
if (led != null) if (led != null)
@ -108,7 +104,7 @@ namespace RGB.NET.Groups
public bool ContainsLed(Led led) public bool ContainsLed(Led led)
{ {
lock (GroupLeds) lock (GroupLeds)
return (led != null) && GroupLeds.Contains(led); return GroupLeds.Contains(led);
} }
/// <summary> /// <summary>

View File

@ -267,11 +267,13 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DG/@EntryIndexedValue">DG</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DG/@EntryIndexedValue">DG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DMX/@EntryIndexedValue">DMX</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DMX/@EntryIndexedValue">DMX</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DRAM/@EntryIndexedValue">DRAM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EK/@EntryIndexedValue">EK</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EK/@EntryIndexedValue">EK</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FM/@EntryIndexedValue">FM</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FM/@EntryIndexedValue">FM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GEZ/@EntryIndexedValue">GEZ</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GEZ/@EntryIndexedValue">GEZ</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HID/@EntryIndexedValue">HID</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HID/@EntryIndexedValue">HID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HS/@EntryIndexedValue">HS</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HS/@EntryIndexedValue">HS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HSV/@EntryIndexedValue">HSV</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IBAN/@EntryIndexedValue">IBAN</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IBAN/@EntryIndexedValue">IBAN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IO/@EntryIndexedValue">IO</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IO/@EntryIndexedValue">IO</s:String>