diff --git a/Documentation/DeviceLayout.xsd b/Documentation/DeviceLayout.xsd index 91ced39..d534089 100644 --- a/Documentation/DeviceLayout.xsd +++ b/Documentation/DeviceLayout.xsd @@ -13,11 +13,17 @@ - - - + + + + + + + + + @@ -28,6 +34,13 @@ + + + + + + + @@ -35,32 +48,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs index b979a1c..7103773 100644 --- a/RGB.NET.Core/Devices/IRGBDevice.cs +++ b/RGB.NET.Core/Devices/IRGBDevice.cs @@ -28,7 +28,7 @@ namespace RGB.NET.Core /// /// Gets the of the . /// - Size Size { get; } + Size Size { get; set; } /// /// Gets the actual of the . @@ -87,6 +87,10 @@ namespace RGB.NET.Core /// Specifies whether all (including clean ones) should be updated. void Update(bool flushLeds = false); + Led? AddLed(LedId ledId, Point location, Size size, object? customData = null); + + Led? RemoveLed(LedId ledId); + #endregion } diff --git a/RGB.NET.Core/Devices/IRGBDeviceInfo.cs b/RGB.NET.Core/Devices/IRGBDeviceInfo.cs index 41379ff..8bf1d90 100644 --- a/RGB.NET.Core/Devices/IRGBDeviceInfo.cs +++ b/RGB.NET.Core/Devices/IRGBDeviceInfo.cs @@ -28,11 +28,8 @@ namespace RGB.NET.Core /// Gets the model-name of the . /// string Model { get; } - - /// - /// Gets the URI of an image of the or null if there is no image. - /// - Uri Image { get; set; } + + object? LayoutMetadata { get; set; } #endregion } diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs index 7613fb2..9766043 100644 --- a/RGB.NET.Core/Leds/Led.cs +++ b/RGB.NET.Core/Leds/Led.cs @@ -169,6 +169,8 @@ namespace RGB.NET.Core /// public object? CustomData { get; } + public object? LayoutMetadata { get; set; } + #endregion #region Constructors diff --git a/RGB.NET.Layout/DeviceLayout.cs b/RGB.NET.Layout/DeviceLayout.cs index dc87418..2f34028 100644 --- a/RGB.NET.Layout/DeviceLayout.cs +++ b/RGB.NET.Layout/DeviceLayout.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.ComponentModel; using System.IO; +using System.Linq; +using System.Xml; using System.Xml.Serialization; using RGB.NET.Core; @@ -12,7 +14,7 @@ namespace RGB.NET.Layout /// [Serializable] [XmlRoot("Device")] - public class DeviceLayout + public class DeviceLayout : IDeviceLayout { #region Properties & Fields @@ -57,13 +59,13 @@ namespace RGB.NET.Layout /// Gets or sets the width of the . /// [XmlElement("Width")] - public double? Width { get; set; } + public double Width { get; set; } /// /// Gets or sets the height of the . /// [XmlElement("Height")] - public double? Height { get; set; } + public double Height { get; set; } /// /// Gets or sets the width of one 'unit' used for the calculation of led positions and sizes. @@ -79,29 +81,20 @@ namespace RGB.NET.Layout [DefaultValue(19.0)] public double LedUnitHeight { get; set; } = 19.0; - /// - /// The path images for this device are collected in. - /// - [XmlElement("ImageBasePath")] - public string? ImageBasePath { get; set; } - - /// - /// The image file for this device. - /// - [XmlElement("DeviceImage")] - public string? DeviceImage { get; set; } + [XmlArray("Leds")] + public List InternalLeds { get; set; } = new(); /// /// Gets or sets a list of representing all the of the . /// - [XmlArray("Leds")] - public List Leds { get; set; } = new(); + [XmlIgnore] + public IEnumerable Leds => InternalLeds; - /// - /// Gets or sets a list of representing the layouts for the images of all the of the . - /// - [XmlArray("LedImageLayouts")] - public List LedImageLayouts { get; set; } = new(); + [XmlElement("CustomData")] + public object? InternalCustomData { get; set; } + + [XmlIgnore] + public object? CustomData { get; set; } #endregion @@ -112,7 +105,7 @@ namespace RGB.NET.Layout /// /// The path to the xml file. /// The deserialized . - public static DeviceLayout? Load(string path) + public static DeviceLayout? Load(string path, Type? customDeviceDataType = null, Type? customLedDataType = null) { if (!File.Exists(path)) return null; @@ -122,13 +115,18 @@ namespace RGB.NET.Layout using StreamReader reader = new(path); DeviceLayout? layout = serializer.Deserialize(reader) as DeviceLayout; - if (layout?.Leds != null) + if (layout != null) + layout.CustomData = layout.GetCustomData(layout.InternalCustomData, customDeviceDataType); + + if (layout?.InternalLeds != null) { LedLayout? lastLed = null; - foreach (LedLayout led in layout.Leds) + foreach (LedLayout led in layout.InternalLeds) { led.CalculateValues(layout, lastLed); lastLed = led; + + led.CustomData = layout.GetCustomData(led.InternalCustomData, customLedDataType); } } @@ -140,6 +138,23 @@ namespace RGB.NET.Layout } } + protected virtual object? GetCustomData(object? customData, Type? type) + { + XmlNode? node = (customData as XmlNode) ?? (customData as IEnumerable)?.FirstOrDefault()?.ParentNode; //HACK DarthAffe 16.01.2021: This gives us the CustomData-Node + if ((node == null) || (type == null)) return null; + + if (type == null) return null; + + using MemoryStream ms = new(); + using StreamWriter writer = new(ms); + + writer.Write(node.OuterXml); + writer.Flush(); + ms.Seek(0, SeekOrigin.Begin); + + return new XmlSerializer(type).Deserialize(ms); + } + #endregion } } diff --git a/RGB.NET.Layout/IDeviceLayout.cs b/RGB.NET.Layout/IDeviceLayout.cs new file mode 100644 index 0000000..c06d9d9 --- /dev/null +++ b/RGB.NET.Layout/IDeviceLayout.cs @@ -0,0 +1,55 @@ +using System.Collections.Generic; +using RGB.NET.Core; + +namespace RGB.NET.Layout +{ + public interface IDeviceLayout + { + /// + /// Gets or sets the name of the . + /// + string? Name { get; } + + /// + /// Gets or sets the description of the . + /// + string? Description { get; } + + /// + /// Gets or sets the of the . + /// + RGBDeviceType Type { get; } + + /// + /// Gets or sets the vendor of the . + /// + string? Vendor { get; } + + /// + /// Gets or sets the model of the . + /// + string? Model { get; } + + /// + /// Gets or sets the of the . + /// + Shape Shape { get; } + + /// + /// Gets or sets the width of the . + /// + double Width { get; } + + /// + /// Gets or sets the height of the . + /// + double Height { get; } + + /// + /// Gets or sets a list of representing all the of the . + /// + IEnumerable Leds { get; } + + object? CustomData { get; } + } +} diff --git a/RGB.NET.Layout/ILedLayout.cs b/RGB.NET.Layout/ILedLayout.cs new file mode 100644 index 0000000..3747a97 --- /dev/null +++ b/RGB.NET.Layout/ILedLayout.cs @@ -0,0 +1,44 @@ +using RGB.NET.Core; + +namespace RGB.NET.Layout +{ + public interface ILedLayout + { + /// + /// Gets or sets the Id of the . + /// + string? Id { get; } + + /// + /// Gets or sets the of the . + /// + Shape Shape { get; } + + /// + /// Gets or sets the vecor-data representing a custom-shape of the . + /// + string? ShapeData { get; } + + /// + /// Gets the x-position of the . + /// + double X { get; } + + /// + /// Gets the y-position of the . + /// + double Y { get; } + + /// + /// Gets the width of the . + /// + double Width { get; } + + /// + /// Gets the height of the . + /// + double Height { get; } + + object? CustomData { get; } + } +} diff --git a/RGB.NET.Layout/LayoutExtension.cs b/RGB.NET.Layout/LayoutExtension.cs new file mode 100644 index 0000000..ec88f27 --- /dev/null +++ b/RGB.NET.Layout/LayoutExtension.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using RGB.NET.Core; + +namespace RGB.NET.Layout +{ + public static class LayoutExtension + { + public static void ApplyTo(this IDeviceLayout layout, IRGBDevice device, bool createMissingLeds = false, bool removeExcessiveLeds = false) + { + device.Size = new Size(layout.Width, layout.Height); + device.DeviceInfo.LayoutMetadata = layout.CustomData; + + HashSet ledIds = new(); + foreach (ILedLayout layoutLed in layout.Leds) + { + if (Enum.TryParse(layoutLed.Id, true, out LedId ledId)) + { + ledIds.Add(ledId); + + Led? led = device[ledId]; + if ((led == null) && createMissingLeds) + led = device.AddLed(ledId, new Point(), new Size()); + + if (led != null) + { + led.Location = new Point(layoutLed.X, layoutLed.Y); + led.Size = new Size(layoutLed.Width, layoutLed.Height); + led.Shape = layoutLed.Shape; + led.ShapeData = layoutLed.ShapeData; + led.LayoutMetadata = layoutLed.CustomData; + } + } + } + + if (removeExcessiveLeds) + { + List ledsToRemove = device.Select(led => led.Id).Where(id => !ledIds.Contains(id)).ToList(); + foreach (LedId led in ledsToRemove) + device.RemoveLed(led); + } + } + } +} diff --git a/RGB.NET.Layout/LedImage.cs b/RGB.NET.Layout/LedImage.cs deleted file mode 100644 index 997ac52..0000000 --- a/RGB.NET.Layout/LedImage.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Xml.Serialization; -using RGB.NET.Core; - -namespace RGB.NET.Layout -{ - /// - /// Represents the serializable image-data of a specific . - /// - [Serializable] - [XmlRoot("LedImage")] - public class LedImage - { - /// - /// Gets or sets the Id of the . - /// - [XmlAttribute("Id")] - public string? Id { get; set; } - - /// - /// Gets or sets the image of the . - /// - [XmlAttribute("Image")] - public string? Image { get; set; } - } -} diff --git a/RGB.NET.Layout/LedImageLayout.cs b/RGB.NET.Layout/LedImageLayout.cs deleted file mode 100644 index 8c0b776..0000000 --- a/RGB.NET.Layout/LedImageLayout.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Xml.Serialization; -using RGB.NET.Core; - -namespace RGB.NET.Layout -{ - /// - /// Represents the serializable collection of for a specific layout. - /// - [Serializable] - [XmlRoot("LedImageLayout")] - public class LedImageLayout - { - /// - /// Gets or sets the layout of the . - /// - [XmlAttribute("Layout")] - [DefaultValue(null)] - public string? Layout { get; set; } - - /// - /// Gets or sets a list of representing the images of all the of the represented layout. - /// - [XmlArray("LedImages")] - public List LedImages { get; set; } = new(); - } -} diff --git a/RGB.NET.Layout/LedLayout.cs b/RGB.NET.Layout/LedLayout.cs index 3447f61..3bab36c 100644 --- a/RGB.NET.Layout/LedLayout.cs +++ b/RGB.NET.Layout/LedLayout.cs @@ -11,7 +11,7 @@ namespace RGB.NET.Layout /// [Serializable] [XmlType("Led")] - public class LedLayout + public class LedLayout : ILedLayout { #region Properties & Fields @@ -61,6 +61,12 @@ namespace RGB.NET.Layout [DefaultValue("1.0")] public string DescriptiveHeight { get; set; } = "1.0"; + [XmlElement("CustomData")] + public object? InternalCustomData { get; set; } + + [XmlIgnore] + public object? CustomData { get; set; } + /// /// Gets or sets the of the . /// @@ -74,25 +80,25 @@ namespace RGB.NET.Layout public string? ShapeData { get; set; } /// - /// Gets or sets the x-position of the . + /// Gets the x-position of the . /// [XmlIgnore] public double X { get; private set; } /// - /// Gets or sets the y-position of the . + /// Gets the y-position of the . /// [XmlIgnore] public double Y { get; private set; } /// - /// Gets or sets the width of the . + /// Gets the width of the . /// [XmlIgnore] public double Width { get; private set; } /// - /// Gets or sets the height of the . + /// Gets the height of the . /// [XmlIgnore] public double Height { get; private set; } @@ -106,7 +112,7 @@ namespace RGB.NET.Layout /// /// The this belongs to. /// The previously calculated. - public void CalculateValues(DeviceLayout device, LedLayout? lastLed) + public virtual void CalculateValues(DeviceLayout device, LedLayout? lastLed) { if (!Enum.TryParse(DescriptiveShape, true, out Shape shape)) { @@ -122,7 +128,7 @@ namespace RGB.NET.Layout Y = GetLocationValue(DescriptiveY, lastLed?.Y ?? 0, Height, lastLed?.Height ?? 0); } - private double GetLocationValue(string value, double lastValue, double currentSize, double lastSize) + protected virtual double GetLocationValue(string value, double lastValue, double currentSize, double lastSize) { try { @@ -159,7 +165,7 @@ namespace RGB.NET.Layout } } - private double GetSizeValue(string value, double unitSize) + protected virtual double GetSizeValue(string value, double unitSize) { try {