using System; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Runtime.Serialization; namespace Netron.Diagramming.Core { /// /// Static class of utility methods /// public static class Utils { public static void DrawRoundRect(Graphics g, Pen p, Rectangle rectangle) { DrawRoundRect(g, p, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, 7F); } public static void DrawRoundRect(Graphics g, Pen p, float X, float Y, float width, float height, float radius) { GraphicsPath path = new GraphicsPath(); path.AddLine(X + radius, Y, X + width - (radius * 2), Y); path.AddArc(X + width - (radius * 2), Y, radius * 2, radius * 2, 270, 90); path.AddLine(X + width, Y + radius, X + width, Y + height - (radius * 2)); path.AddArc(X + width - (radius * 2), Y + height - (radius * 2), radius * 2, radius * 2, 0, 90); path.AddLine(X + width - (radius * 2), Y + height, X + radius, Y + height); path.AddArc(X, Y + height - (radius * 2), radius * 2, radius * 2, 90, 90); path.AddLine(X, Y + height - (radius * 2), X, Y + radius); path.AddArc(X, Y, radius * 2, radius * 2, 180, 90); path.CloseFigure(); g.DrawPath(p, path); path.Dispose(); } /// /// Returns the bounding rectangle of the given collection of entities. /// /// /// public static Rectangle BoundingRectangle(CollectionBase collection) { //get the bounding rectangle bool first = true; Rectangle rec = Rectangle.Empty; foreach (IDiagramEntity entity in collection) { if (first) { rec = entity.Rectangle; first = false; } else rec = Rectangle.Union(rec, entity.Rectangle); } return rec; } /// /// Depth-first traversal of an /// /// /// public static void TraverseCollect(IGroup group, ref CollectionBase collection) { #region Checks if (group == null) throw new InconsistencyException("Cannot collect entities of a 'null' IGroup"); if (collection == null) throw new InconsistencyException("You need to instantiate a collection before using this method."); #endregion foreach (IDiagramEntity entity in group.Entities) { if (entity is IGroup) TraverseCollect(entity as IGroup, ref collection); else collection.Add(entity); } } // Given H,S,L in range of 0-1 // Returns a Color (RGB struct) in range of 0-255 /// /// HSL to RGB conversion. /// /// The h. /// The sl. /// The l. /// public static ColorRGB HSL2RGB(double h, double sl, double l) { double v; double r, g, b; r = l; // default to gray g = l; b = l; v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl); if (v > 0) { double m; double sv; int sextant; double fract, vsf, mid1, mid2; m = l + l - v; sv = (v - m) / v; h *= 6.0; sextant = (int)h; fract = h - sextant; vsf = v * sv * fract; mid1 = m + vsf; mid2 = v - vsf; switch (sextant) { case 0: r = v; g = mid1; b = m; break; case 1: r = mid2; g = v; b = m; break; case 2: r = m; g = v; b = mid1; break; case 3: r = m; g = mid2; b = v; break; case 4: r = mid1; g = m; b = v; break; case 5: r = v; g = m; b = mid2; break; } } ColorRGB rgb = new ColorRGB(); rgb.R = Convert.ToByte(r * 255.0f); rgb.G = Convert.ToByte(g * 255.0f); rgb.B = Convert.ToByte(b * 255.0f); return rgb; } // Given a Color (RGB Struct) in range of 0-255 // Return H,S,L in range of 0-1 /// /// RGB to HSL conversion /// /// The RGB. /// The h. /// The s. /// The l. public static void RGB2HSL(ColorRGB rgb, out double h, out double s, out double l) { double r = rgb.R / 255.0; double g = rgb.G / 255.0; double b = rgb.B / 255.0; double v; double m; double vm; double r2, g2, b2; h = 0; // default to black s = 0; l = 0; v = Math.Max(r, g); v = Math.Max(v, b); m = Math.Min(r, g); m = Math.Min(m, b); l = (m + v) / 2.0; if (l <= 0.0) { return; } vm = v - m; s = vm; if (s > 0.0) { s /= (l <= 0.5) ? (v + m) : (2.0 - v - m); } else { return; } r2 = (v - r) / vm; g2 = (v - g) / vm; b2 = (v - b) / vm; if (r == v) { h = (g == m ? 5.0 + b2 : 1.0 - g2); } else if (g == v) { h = (b == m ? 1.0 + r2 : 3.0 - b2); } else { h = (r == m ? 3.0 + g2 : 5.0 - r2); } h /= 6.0; } /// /// Constrains the type. /// /// The type. public static void ConstrainType(Type type) { bool serializable = type.IsSerializable; if (serializable == false) { string message = "The type " + type + " is not serializable"; throw new SerializationException(message); } bool genericType = type.IsGenericType; if (genericType) { Type[] typeArguments = type.GetGenericArguments(); Debug.Assert(typeArguments.Length >= 1); Array.ForEach(typeArguments, ConstrainType); } } } /// /// Utility struct for color conversions /// public struct ColorRGB { #region Fields private byte r; private byte g; private byte b; #endregion /// /// Gets or sets the Red value. /// /// The R. public byte R { get { return r; } set { r = value; } } /// /// Gets or sets the Green value. /// /// The G. public byte G { get { return g; } set { g = value; } } /// /// Gets or sets the Blue value. /// /// The B. public byte B { get { return b; } set { b = value; } } /// /// Initializes a new instance of the class. /// /// The value. public ColorRGB(Color value) { this.r = value.R; this.g = value.G; this.b = value.B; } /// /// Implicit conversion of the specified RGB. /// /// The RGB. /// public static implicit operator Color(ColorRGB rgb) { Color c = Color.FromArgb(rgb.R, rgb.G, rgb.B); return c; } /// /// Explicit conversion of the specified c. /// /// The c. /// public static explicit operator ColorRGB(Color c) { return new ColorRGB(c); } } }