diff --git a/RGB.NET.Core/Positioning/Scale.cs b/RGB.NET.Core/Positioning/Scale.cs index 973bf9cf..18644e6c 100644 --- a/RGB.NET.Core/Positioning/Scale.cs +++ b/RGB.NET.Core/Positioning/Scale.cs @@ -50,6 +50,12 @@ public Scale(float horizontal, float vertical) #region Methods + /// + /// Converts the and value of this to a human-readable string. + /// + /// A string that contains the and value of this . For example "[Horizontal: 1, Vertical: 0.5]". + public override string ToString() => $"[Horizontal: {Horizontal}, Vertical: {Vertical}]\""; + /// /// Tests whether the specified is equivalent to this . /// diff --git a/RGB.NET.Layout/DeviceLayout.cs b/RGB.NET.Layout/DeviceLayout.cs index 24efd371..e33e7609 100644 --- a/RGB.NET.Layout/DeviceLayout.cs +++ b/RGB.NET.Layout/DeviceLayout.cs @@ -174,7 +174,7 @@ public class DeviceLayout : IDeviceLayout /// The deserialized custom data object. 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 + XmlNode? node = (customData as XmlNode) ?? (customData as IEnumerable)?.FirstOrDefault(x => x.ParentNode != null)?.ParentNode; //HACK DarthAffe 16.01.2021: This gives us the CustomData-Node if ((node == null) || (type == null)) return null; using MemoryStream ms = new(); diff --git a/RGB.NET.Layout/LayoutExtension.cs b/RGB.NET.Layout/LayoutExtension.cs index a6666372..915380b1 100644 --- a/RGB.NET.Layout/LayoutExtension.cs +++ b/RGB.NET.Layout/LayoutExtension.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Xml.Serialization; using RGB.NET.Core; namespace RGB.NET.Layout; @@ -51,4 +53,48 @@ public static void ApplyTo(this IDeviceLayout layout, IRGBDevice device, bool cr device.RemoveLed(led); } } + + /// + /// Saves the specified layout to the given location. + /// + /// The layout to save. + /// The location to save to. + public static void Save(this IDeviceLayout layout, string targetFile) + { + using FileStream fs = new(targetFile, FileMode.Create); + layout.Save(fs); + } + + /// + /// Saves the specified layout to the given stream. + /// + /// The layout to save. + /// The stream to save to. + public static void Save(this IDeviceLayout layout, Stream stream) + { + Type? customDataType = layout.CustomData?.GetType(); + Type? customLedDataType = layout.Leds.FirstOrDefault(x => x.CustomData != null)?.GetType(); + + Type[] customTypes; + if ((customDataType != null) && (customLedDataType != null)) + customTypes = new[] { customDataType, customLedDataType }; + else if (customDataType != null) + customTypes = new[] { customDataType }; + else if (customLedDataType != null) + customTypes = new[] { customLedDataType }; + else + customTypes = Array.Empty(); + + if (layout is DeviceLayout deviceLayout) + { + deviceLayout.InternalCustomData = deviceLayout.CustomData; + + foreach (ILedLayout led in deviceLayout.Leds) + if (led is LedLayout ledLayout) + ledLayout.InternalCustomData = ledLayout.CustomData; + } + + XmlSerializer serializer = new(typeof(DeviceLayout), null, customTypes, null, null); + serializer.Serialize(stream, layout); + } } \ No newline at end of file