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 }