using System;
using System.ComponentModel;
using System.Globalization;
using System.Xml.Serialization;
using RGB.NET.Core;
namespace RGB.NET.Layout;
///
/// Represents the serializable layout of a .
///
[Serializable]
[XmlType("Led")]
public class LedLayout : ILedLayout
{
#region Properties & Fields
///
/// Gets or sets the Id of the .
///
[XmlAttribute("Id")]
public string? Id { get; set; }
///
/// Gets or sets the descriptive of the .
/// This property is for XML-serialization only and should not be directly accessed.
///
[XmlElement("Shape")]
[DefaultValue("Rectangle")]
public string DescriptiveShape { get; set; } = "Rectangle";
///
/// Gets or sets the descriptive x-position of the .
/// This property is for XML-serialization only and should not be directly accessed.
///
[XmlElement("X")]
[DefaultValue("+")]
public string DescriptiveX { get; set; } = "+";
///
/// Gets or sets the descriptive y-position of the .
/// This property is for XML-serialization only and should not be directly accessed.
///
[XmlElement("Y")]
[DefaultValue("=")]
public string DescriptiveY { get; set; } = "=";
///
/// Gets or sets the descriptive width of the .
/// This property is for XML-serialization only and should not be directly accessed.
///
[XmlElement("Width")]
[DefaultValue("1.0")]
public string DescriptiveWidth { get; set; } = "1.0";
///
/// Gets or sets the descriptive height of the .
/// This property is for XML-serialization only and should not be directly accessed.
///
[XmlElement("Height")]
[DefaultValue("1.0")]
public string DescriptiveHeight { get; set; } = "1.0";
///
/// Gets or sets the internal custom data of this layout.
/// Normally you should use to access or set this data.
///
[XmlElement("CustomData")]
public object? InternalCustomData { get; set; }
///
[XmlIgnore]
public object? CustomData { get; set; }
///
/// Gets or sets the of the .
///
[XmlIgnore]
public Shape Shape { get; set; }
///
/// Gets or sets the vecor-data representing a custom-shape of the .
///
[XmlIgnore]
public string? ShapeData { get; set; }
///
/// Gets the x-position of the .
///
[XmlIgnore]
public float X { get; private set; }
///
/// Gets the y-position of the .
///
[XmlIgnore]
public float Y { get; private set; }
///
/// Gets the width of the .
///
[XmlIgnore]
public float Width { get; private set; }
///
/// Gets the height of the .
///
[XmlIgnore]
public float Height { get; private set; }
#endregion
#region Methods
///
/// Calculates the position- and size-data from the respective descriptive values.
///
/// The this belongs to.
/// The previously calculated.
public virtual void CalculateValues(DeviceLayout device, LedLayout? lastLed)
{
if (!Enum.TryParse(DescriptiveShape, true, out Shape shape))
{
shape = Shape.Custom;
ShapeData = DescriptiveShape;
}
Shape = shape;
Width = GetSizeValue(DescriptiveWidth, device.LedUnitWidth);
Height = GetSizeValue(DescriptiveHeight, device.LedUnitHeight);
X = GetLocationValue(DescriptiveX, lastLed?.X ?? 0, Width, lastLed?.Width ?? 0);
Y = GetLocationValue(DescriptiveY, lastLed?.Y ?? 0, Height, lastLed?.Height ?? 0);
}
///
/// Gets the calculated location-value from the internal representation.
///
/// The value provided by the layout.
/// The location of the last calculated LED.
/// The size of the current LED.
/// The size of the last loaded LED.
/// The location-value of the LED.
protected virtual float GetLocationValue(string value, float lastValue, float currentSize, float lastSize)
{
try
{
if (string.IsNullOrWhiteSpace(value)) return 0;
value = value.Replace(" ", string.Empty);
if (string.Equals(value, "=", StringComparison.Ordinal))
return lastValue;
if (string.Equals(value, "+", StringComparison.Ordinal))
return lastValue + lastSize;
if (value.StartsWith("+", StringComparison.Ordinal))
return lastValue + lastSize + float.Parse(value[1..], CultureInfo.InvariantCulture);
if (string.Equals(value, "-", StringComparison.Ordinal))
return lastValue - currentSize;
if (value.StartsWith("-", StringComparison.Ordinal))
return lastValue - currentSize - float.Parse(value[1..], CultureInfo.InvariantCulture);
if (string.Equals(value, "~", StringComparison.Ordinal))
return (lastValue + lastSize) - currentSize;
if (value.StartsWith("~", StringComparison.Ordinal))
return (lastValue + lastSize) - currentSize - float.Parse(value[1..], CultureInfo.InvariantCulture);
return float.Parse(value, CultureInfo.InvariantCulture);
}
catch
{
return 0;
}
}
///
/// Gets the calculated size-value from the internal representation.
///
/// The value provided by the layout.
/// The absolute size of one 'unit'.
/// The size-value of the LED.
protected virtual float GetSizeValue(string value, float unitSize)
{
try
{
if (string.IsNullOrWhiteSpace(value)) return 0;
value = value.Replace(" ", string.Empty);
if (value.EndsWith("mm", StringComparison.OrdinalIgnoreCase))
return float.Parse(value[..^2], CultureInfo.InvariantCulture);
return unitSize * float.Parse(value, CultureInfo.InvariantCulture);
}
catch
{
return 0;
}
}
#endregion
}