namespace Dashboard { public enum MeasurementUnit { /// /// The default unit. A size of a single picture element. /// Pixel, /// /// 1/72th of an inch traditional in graphics design. /// Point, /// /// The universal length unit for small distances. /// Millimeter, /// /// An inverse proportional unit with respect to the container size. /// Star, /// /// A directly proportional unit with respect to the container size. /// Percent, } public record struct AdvancedMetric(MeasurementUnit Unit, float Value) { public AdvancedMetric Convert(MeasurementUnit target, float dpi, float rel, int stars) { if (Unit == target) return this; float pixels = Unit switch { MeasurementUnit.Pixel => Value, MeasurementUnit.Point => Value * (72f / dpi), MeasurementUnit.Millimeter => Value * (28.3464566929f / dpi), MeasurementUnit.Star => Value * rel / stars, MeasurementUnit.Percent => Value * rel / 100, _ => throw new Exception(), }; float value = target switch { MeasurementUnit.Pixel => pixels, MeasurementUnit.Point => Value * (dpi / 72f), // MeasurementUnit.Millimeter => }; return new AdvancedMetric(target, value); } public override string ToString() { return $"{Value} {Unit.ToShortString()}"; } public static bool TryParse(ReadOnlySpan str, out AdvancedMetric metric) { metric = default; return false; } public static AdvancedMetric Parse(ReadOnlySpan str) => TryParse(str, out AdvancedMetric metric) ? metric : throw new Exception($"Could not parse the value '{str}'."); } public static class MeasurementExtensions { public static bool IsRelative(this MeasurementUnit unit) => unit switch { MeasurementUnit.Star or MeasurementUnit.Percent => true, _ => false, }; public static bool IsAbsolute(this MeasurementUnit unit) => !IsRelative(unit); public static string ToShortString(this MeasurementUnit unit) => unit switch { MeasurementUnit.Pixel => "px", MeasurementUnit.Point => "pt", MeasurementUnit.Millimeter => "mm", MeasurementUnit.Star => "*", MeasurementUnit.Percent => "%", _ => throw new Exception("Unknown unit."), }; } }