[2768] | 1 | using System;
|
---|
| 2 | using System.Collections;
|
---|
| 3 | using System.Collections.Generic;
|
---|
| 4 | using System.Text;
|
---|
| 5 | using System.Drawing;
|
---|
| 6 | using System.Drawing.Drawing2D;
|
---|
| 7 | using System.IO;
|
---|
| 8 | using System.Diagnostics;
|
---|
| 9 | using System.Runtime.Serialization;
|
---|
| 10 | namespace Netron.Diagramming.Core
|
---|
| 11 | {
|
---|
| 12 | /// <summary>
|
---|
| 13 | /// Static class of utility methods
|
---|
| 14 | /// </summary>
|
---|
| 15 | public static class Utils
|
---|
| 16 | {
|
---|
| 17 | public static void DrawRoundRect(Graphics g, Pen p, Rectangle rectangle)
|
---|
| 18 | {
|
---|
| 19 | DrawRoundRect(g, p, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, 7F);
|
---|
| 20 | }
|
---|
| 21 | public static void DrawRoundRect(Graphics g, Pen p, float X, float Y, float width, float height, float radius)
|
---|
| 22 | {
|
---|
| 23 |
|
---|
| 24 | GraphicsPath path = new GraphicsPath();
|
---|
| 25 | path.AddLine(X + radius, Y, X + width - (radius * 2), Y);
|
---|
| 26 | path.AddArc(X + width - (radius * 2), Y, radius * 2, radius * 2, 270, 90);
|
---|
| 27 | path.AddLine(X + width, Y + radius, X + width, Y + height - (radius * 2));
|
---|
| 28 | path.AddArc(X + width - (radius * 2), Y + height - (radius * 2), radius * 2, radius * 2, 0, 90);
|
---|
| 29 | path.AddLine(X + width - (radius * 2), Y + height, X + radius, Y + height);
|
---|
| 30 | path.AddArc(X, Y + height - (radius * 2), radius * 2, radius * 2, 90, 90);
|
---|
| 31 | path.AddLine(X, Y + height - (radius * 2), X, Y + radius);
|
---|
| 32 | path.AddArc(X, Y, radius * 2, radius * 2, 180, 90);
|
---|
| 33 | path.CloseFigure();
|
---|
| 34 |
|
---|
| 35 | g.DrawPath(p, path);
|
---|
| 36 | path.Dispose();
|
---|
| 37 | }
|
---|
| 38 |
|
---|
| 39 | /// <summary>
|
---|
| 40 | /// Returns the bounding rectangle of the given collection of entities.
|
---|
| 41 | /// </summary>
|
---|
| 42 | /// <param name="collection"></param>
|
---|
| 43 | /// <returns></returns>
|
---|
| 44 | public static Rectangle BoundingRectangle(CollectionBase<IDiagramEntity> collection)
|
---|
| 45 | {
|
---|
| 46 | //get the bounding rectangle
|
---|
| 47 | bool first = true;
|
---|
| 48 | Rectangle rec = Rectangle.Empty;
|
---|
| 49 | foreach (IDiagramEntity entity in collection)
|
---|
| 50 | {
|
---|
| 51 | if (first)
|
---|
| 52 | {
|
---|
| 53 | rec = entity.Rectangle;
|
---|
| 54 | first = false;
|
---|
| 55 | }
|
---|
| 56 | else
|
---|
| 57 | rec = Rectangle.Union(rec, entity.Rectangle);
|
---|
| 58 | }
|
---|
| 59 | return rec;
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | /// <summary>
|
---|
| 63 | /// Depth-first traversal of an <see cref="IGroup"/>
|
---|
| 64 | /// </summary>
|
---|
| 65 | /// <param name="group"></param>
|
---|
| 66 | /// <param name="collection"></param>
|
---|
| 67 | public static void TraverseCollect(IGroup group, ref CollectionBase<IDiagramEntity> collection)
|
---|
| 68 | {
|
---|
| 69 | #region Checks
|
---|
| 70 | if(group == null)
|
---|
| 71 | throw new InconsistencyException("Cannot collect entities of a 'null' IGroup");
|
---|
| 72 | if(collection == null)
|
---|
| 73 | throw new InconsistencyException("You need to instantiate a collection before using this method.");
|
---|
| 74 | #endregion
|
---|
| 75 |
|
---|
| 76 | foreach(IDiagramEntity entity in group.Entities)
|
---|
| 77 | {
|
---|
| 78 | if(entity is IGroup)
|
---|
| 79 | TraverseCollect(entity as IGroup, ref collection);
|
---|
| 80 | else
|
---|
| 81 | collection.Add(entity);
|
---|
| 82 | }
|
---|
| 83 |
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | // Given H,S,L in range of 0-1
|
---|
| 87 |
|
---|
| 88 | // Returns a Color (RGB struct) in range of 0-255
|
---|
| 89 |
|
---|
| 90 | /// <summary>
|
---|
| 91 | /// HSL to RGB conversion.
|
---|
| 92 | /// </summary>
|
---|
| 93 | /// <param name="h">The h.</param>
|
---|
| 94 | /// <param name="sl">The sl.</param>
|
---|
| 95 | /// <param name="l">The l.</param>
|
---|
| 96 | /// <returns></returns>
|
---|
| 97 | public static ColorRGB HSL2RGB(double h, double sl, double l)
|
---|
| 98 | {
|
---|
| 99 |
|
---|
| 100 | double v;
|
---|
| 101 | double r, g, b;
|
---|
| 102 | r = l; // default to gray
|
---|
| 103 | g = l;
|
---|
| 104 | b = l;
|
---|
| 105 | v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
|
---|
| 106 | if(v > 0)
|
---|
| 107 | {
|
---|
| 108 | double m;
|
---|
| 109 | double sv;
|
---|
| 110 | int sextant;
|
---|
| 111 | double fract, vsf, mid1, mid2;
|
---|
| 112 |
|
---|
| 113 | m = l + l - v;
|
---|
| 114 | sv = (v - m) / v;
|
---|
| 115 | h *= 6.0;
|
---|
| 116 | sextant = (int) h;
|
---|
| 117 | fract = h - sextant;
|
---|
| 118 | vsf = v * sv * fract;
|
---|
| 119 | mid1 = m + vsf;
|
---|
| 120 | mid2 = v - vsf;
|
---|
| 121 | switch(sextant)
|
---|
| 122 | {
|
---|
| 123 | case 0:
|
---|
| 124 | r = v;
|
---|
| 125 | g = mid1;
|
---|
| 126 | b = m;
|
---|
| 127 | break;
|
---|
| 128 | case 1:
|
---|
| 129 | r = mid2;
|
---|
| 130 | g = v;
|
---|
| 131 | b = m;
|
---|
| 132 | break;
|
---|
| 133 | case 2:
|
---|
| 134 | r = m;
|
---|
| 135 | g = v;
|
---|
| 136 | b = mid1;
|
---|
| 137 | break;
|
---|
| 138 | case 3:
|
---|
| 139 | r = m;
|
---|
| 140 | g = mid2;
|
---|
| 141 | b = v;
|
---|
| 142 | break;
|
---|
| 143 | case 4:
|
---|
| 144 | r = mid1;
|
---|
| 145 | g = m;
|
---|
| 146 | b = v;
|
---|
| 147 | break;
|
---|
| 148 | case 5:
|
---|
| 149 | r = v;
|
---|
| 150 | g = m;
|
---|
| 151 | b = mid2;
|
---|
| 152 | break;
|
---|
| 153 | }
|
---|
| 154 | }
|
---|
| 155 | ColorRGB rgb = new ColorRGB();
|
---|
| 156 | rgb.R = Convert.ToByte(r * 255.0f);
|
---|
| 157 | rgb.G = Convert.ToByte(g * 255.0f);
|
---|
| 158 | rgb.B = Convert.ToByte(b * 255.0f);
|
---|
| 159 | return rgb;
|
---|
| 160 |
|
---|
| 161 | }
|
---|
| 162 |
|
---|
| 163 | // Given a Color (RGB Struct) in range of 0-255
|
---|
| 164 |
|
---|
| 165 | // Return H,S,L in range of 0-1
|
---|
| 166 |
|
---|
| 167 | /// <summary>
|
---|
| 168 | /// RGB to HSL conversion
|
---|
| 169 | /// </summary>
|
---|
| 170 | /// <param name="rgb">The RGB.</param>
|
---|
| 171 | /// <param name="h">The h.</param>
|
---|
| 172 | /// <param name="s">The s.</param>
|
---|
| 173 | /// <param name="l">The l.</param>
|
---|
| 174 | public static void RGB2HSL(ColorRGB rgb, out double h, out double s, out double l)
|
---|
| 175 | {
|
---|
| 176 | double r = rgb.R / 255.0;
|
---|
| 177 | double g = rgb.G / 255.0;
|
---|
| 178 | double b = rgb.B / 255.0;
|
---|
| 179 | double v;
|
---|
| 180 | double m;
|
---|
| 181 | double vm;
|
---|
| 182 | double r2, g2, b2;
|
---|
| 183 |
|
---|
| 184 | h = 0; // default to black
|
---|
| 185 | s = 0;
|
---|
| 186 | l = 0;
|
---|
| 187 | v = Math.Max(r, g);
|
---|
| 188 | v = Math.Max(v, b);
|
---|
| 189 | m = Math.Min(r, g);
|
---|
| 190 | m = Math.Min(m, b);
|
---|
| 191 |
|
---|
| 192 | l = (m + v) / 2.0;
|
---|
| 193 | if(l <= 0.0)
|
---|
| 194 | {
|
---|
| 195 | return;
|
---|
| 196 | }
|
---|
| 197 | vm = v - m;
|
---|
| 198 | s = vm;
|
---|
| 199 | if(s > 0.0)
|
---|
| 200 | {
|
---|
| 201 | s /= (l <= 0.5) ? (v + m) : (2.0 - v - m);
|
---|
| 202 | }
|
---|
| 203 | else
|
---|
| 204 | {
|
---|
| 205 | return;
|
---|
| 206 | }
|
---|
| 207 | r2 = (v - r) / vm;
|
---|
| 208 | g2 = (v - g) / vm;
|
---|
| 209 | b2 = (v - b) / vm;
|
---|
| 210 | if(r == v)
|
---|
| 211 | {
|
---|
| 212 | h = (g == m ? 5.0 + b2 : 1.0 - g2);
|
---|
| 213 | }
|
---|
| 214 | else if(g == v)
|
---|
| 215 | {
|
---|
| 216 | h = (b == m ? 1.0 + r2 : 3.0 - b2);
|
---|
| 217 | }
|
---|
| 218 | else
|
---|
| 219 | {
|
---|
| 220 | h = (r == m ? 3.0 + g2 : 5.0 - r2);
|
---|
| 221 | }
|
---|
| 222 | h /= 6.0;
|
---|
| 223 | }
|
---|
| 224 | /// <summary>
|
---|
| 225 | /// Constrains the type.
|
---|
| 226 | /// </summary>
|
---|
| 227 | /// <param name="type">The type.</param>
|
---|
| 228 | public static void ConstrainType(Type type)
|
---|
| 229 | {
|
---|
| 230 | bool serializable = type.IsSerializable;
|
---|
| 231 | if(serializable == false)
|
---|
| 232 | {
|
---|
| 233 | string message = "The type " + type + " is not serializable";
|
---|
| 234 | throw new SerializationException(message);
|
---|
| 235 | }
|
---|
| 236 | bool genericType = type.IsGenericType;
|
---|
| 237 |
|
---|
| 238 | if(genericType)
|
---|
| 239 | {
|
---|
| 240 | Type[] typeArguments = type.GetGenericArguments();
|
---|
| 241 | Debug.Assert(typeArguments.Length >= 1);
|
---|
| 242 | Array.ForEach(typeArguments, ConstrainType);
|
---|
| 243 | }
|
---|
| 244 | }
|
---|
| 245 |
|
---|
| 246 |
|
---|
| 247 | }
|
---|
| 248 | /// <summary>
|
---|
| 249 | /// Utility struct for color conversions
|
---|
| 250 | /// </summary>
|
---|
| 251 | public struct ColorRGB
|
---|
| 252 | {
|
---|
| 253 | #region Fields
|
---|
| 254 | private byte r;
|
---|
| 255 | private byte g;
|
---|
| 256 | private byte b;
|
---|
| 257 | #endregion
|
---|
| 258 |
|
---|
| 259 | /// <summary>
|
---|
| 260 | /// Gets or sets the Red value.
|
---|
| 261 | /// </summary>
|
---|
| 262 | /// <value>The R.</value>
|
---|
| 263 | public byte R
|
---|
| 264 | {
|
---|
| 265 | get { return r; }
|
---|
| 266 | set { r = value; }
|
---|
| 267 | }
|
---|
| 268 |
|
---|
| 269 |
|
---|
| 270 | /// <summary>
|
---|
| 271 | /// Gets or sets the Green value.
|
---|
| 272 | /// </summary>
|
---|
| 273 | /// <value>The G.</value>
|
---|
| 274 | public byte G
|
---|
| 275 | {
|
---|
| 276 | get { return g; }
|
---|
| 277 | set { g = value; }
|
---|
| 278 | }
|
---|
| 279 |
|
---|
| 280 |
|
---|
| 281 |
|
---|
| 282 | /// <summary>
|
---|
| 283 | /// Gets or sets the Blue value.
|
---|
| 284 | /// </summary>
|
---|
| 285 | /// <value>The B.</value>
|
---|
| 286 | public byte B
|
---|
| 287 | {
|
---|
| 288 | get { return b; }
|
---|
| 289 | set { b = value; }
|
---|
| 290 | }
|
---|
| 291 | /// <summary>
|
---|
| 292 | /// Initializes a new instance of the <see cref="T:ColorRGB"/> class.
|
---|
| 293 | /// </summary>
|
---|
| 294 | /// <param name="value">The value.</param>
|
---|
| 295 | public ColorRGB(Color value)
|
---|
| 296 | {
|
---|
| 297 | this.r = value.R;
|
---|
| 298 | this.g = value.G;
|
---|
| 299 | this.b = value.B;
|
---|
| 300 | }
|
---|
| 301 | /// <summary>
|
---|
| 302 | /// Implicit conversion of the specified RGB.
|
---|
| 303 | /// </summary>
|
---|
| 304 | /// <param name="rgb">The RGB.</param>
|
---|
| 305 | /// <returns></returns>
|
---|
| 306 | public static implicit operator Color(ColorRGB rgb)
|
---|
| 307 | {
|
---|
| 308 | Color c = Color.FromArgb(rgb.R, rgb.G, rgb.B);
|
---|
| 309 | return c;
|
---|
| 310 | }
|
---|
| 311 | /// <summary>
|
---|
| 312 | /// Explicit conversion of the specified c.
|
---|
| 313 | /// </summary>
|
---|
| 314 | /// <param name="c">The c.</param>
|
---|
| 315 | /// <returns></returns>
|
---|
| 316 | public static explicit operator ColorRGB(Color c)
|
---|
| 317 | {
|
---|
| 318 | return new ColorRGB(c);
|
---|
| 319 | }
|
---|
| 320 | }
|
---|
| 321 |
|
---|
| 322 |
|
---|
| 323 |
|
---|
| 324 |
|
---|
| 325 | }
|
---|