// Copyright (c) 2007-2008, Gaudenz Alder
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Xml;
using System.Text;
using System.Drawing;
using System.Security.Cryptography;
using System.Windows.Forms;
namespace com.mxgraph
{
///
/// Contains various helper methods for use with mxGraph.
///
public class mxUtils
{
///
/// Returns the size of the given label.
///
public static mxRectangle GetLabelSize(string label, Dictionary style, int width)
{
return GetSizeForString(label, GetFont(style), width);
}
///
/// Returns the paint bounds for the given label.
///
///
public static mxRectangle GetLabelPaintBounds(String label,
Dictionary style, bool isHtml, mxPoint offset,
mxRectangle vertexBounds, double scale)
{
bool horizontal = mxUtils.IsTrue(style, mxConstants.STYLE_HORIZONTAL, true);
int w = 0;
if (vertexBounds != null &&
GetString(style, mxConstants.STYLE_WHITE_SPACE, "nowrap").Equals("wrap"))
{
if (horizontal)
{
w = (int)(vertexBounds.Width / scale);
}
else
{
w = (int)(vertexBounds.Height / scale);
}
}
mxRectangle size = mxUtils.GetLabelSize(label, style, w);
double x = offset.X;
double y = offset.Y;
double width = 0;
double height = 0;
if (vertexBounds != null)
{
x += vertexBounds.X;
y += vertexBounds.Y;
// Limits the label to the swimlane title
if (mxUtils.GetString(style, mxConstants.STYLE_SHAPE, "").Equals(
mxConstants.SHAPE_SWIMLANE))
{
double start = mxUtils.GetDouble(style, mxConstants.STYLE_STARTSIZE,
mxConstants.DEFAULT_STARTSIZE) * scale;
if (horizontal)
{
width += vertexBounds.Width;
height += start;
}
else
{
width += start;
height += vertexBounds.Height;
}
}
else
{
width += vertexBounds.Width;
height += vertexBounds.Height;
}
}
return mxUtils.GetScaledLabelBounds(x, y,
size, width, height, style, scale);
}
///
/// Returns the bounds for a label for the given location and size, taking
/// into account the alignment and spacing in the specified style, as well
/// as the width and height of the rectangle that contains the label.
/// (For edge labels this width and height is 0.) The scale is used to scale
/// the given size and the spacings in the specified style.
///
public static mxRectangle GetScaledLabelBounds(double x, double y, mxRectangle size,
double outerWidth, double outerHeight, Dictionary style, double scale)
{
// Adds an inset of 3 pixels
double inset = mxConstants.LABEL_INSET* scale;
// Scales the size of the label
double width = size.Width * scale + 2 * inset;
double height = size.Height * scale;
// Gets the global spacing and orientation
bool horizontal = IsTrue(style, mxConstants.STYLE_HORIZONTAL, true);
int spacing = (int)(GetInt(style, mxConstants.STYLE_SPACING) * scale);
// Gets the alignment settings
Object align = GetString(style, mxConstants.STYLE_ALIGN,
mxConstants.ALIGN_CENTER);
Object valign = GetString(style, mxConstants.STYLE_VERTICAL_ALIGN,
mxConstants.ALIGN_MIDDLE);
// Gets the vertical spacing
int top = (int)(GetInt(style, mxConstants.STYLE_SPACING_TOP) * scale);
int bottom = (int)(GetInt(style,
mxConstants.STYLE_SPACING_BOTTOM) * scale);
// Gets the horizontal spacing
int left = (int)(GetInt(style, mxConstants.STYLE_SPACING_LEFT) * scale);
int right = (int)(GetInt(style,
mxConstants.STYLE_SPACING_RIGHT) * scale);
// Applies the orientation to the spacings
if (!horizontal)
{
int tmp = top;
top = right;
right = bottom;
bottom = left;
left = tmp;
double tmp2 = width;
width = height;
height = tmp2;
}
// Computes the position of the label for the horizontal alignment
if ((horizontal && align.Equals(mxConstants.ALIGN_CENTER))
|| (!horizontal && valign.Equals(mxConstants.ALIGN_MIDDLE)))
{
x += (outerWidth - width) / 2 + left - right;
}
else if ((horizontal && align.Equals(mxConstants.ALIGN_RIGHT))
|| (!horizontal && valign.Equals(mxConstants.ALIGN_BOTTOM)))
{
x += outerWidth - width - spacing - right;
}
else
{
x += spacing + left;
}
// Computes the position of the label for the vertical alignment
if ((!horizontal && align.Equals(mxConstants.ALIGN_CENTER))
|| (horizontal && valign.Equals(mxConstants.ALIGN_MIDDLE)))
{
y += (outerHeight - height) / 2 + top - bottom;
}
else if ((!horizontal && align.Equals(mxConstants.ALIGN_LEFT))
|| (horizontal && valign.Equals(mxConstants.ALIGN_BOTTOM)))
{
y += outerHeight - height - spacing - bottom;
}
else
{
y += spacing + top;
}
return new mxRectangle(x, y, width, height);
}
///
/// Returns the size of the given text.
///
/// String whose size should be returned.
/// Specifies the font that should be used.
/// Returns the size of the given text.
public static mxRectangle GetSizeForString(String text, Font font)
{
return GetSizeForString(text, font, 0);
}
///
/// Returns an mxRectangle with the size (width and height in pixels) of
/// the given text.
///
/// String whose size should be returned.
/// Specifies the font that should be used.
/// Specifies the width of the text block for word wrapping.
/// Returns the size of the given text.
public static mxRectangle GetSizeForString(String text, Font font, int width)
{
TextFormatFlags flags = TextFormatFlags.Default;
if (width > 0)
{
flags |= TextFormatFlags.WordBreak;
}
Size proposedSize = new Size(width, 0);
Size result = TextRenderer.MeasureText(text, font, proposedSize, flags);
return new mxRectangle(0, 0, result.Width, result.Height);
}
///
/// Converts the given degree to radians.
///
public static double ToRadians(double deg)
{
return Math.PI * deg / 180.0;
}
///
/// Converts the given arc to a series of curves.
///
///
///
///
///
///
///
///
///
///
///
public static double[] ArcToCurves(double x0, double y0, double r1, double r2, double angle, double largeArcFlag, double sweepFlag, double x, double y)
{
x -= x0;
y -= y0;
if (r1 == 0 || r2 == 0)
{
return new double[0];
}
double fS = sweepFlag;
double psai = angle;
r1 = Math.Abs(r1);
r2 = Math.Abs(r2);
double ctx = -x / 2;
double cty = -y / 2;
double cpsi = Math.Cos(psai * Math.PI / 180);
double spsi = Math.Sin(psai * Math.PI / 180);
double rxd = cpsi * ctx + spsi * cty;
double ryd = -1 * spsi * ctx + cpsi * cty;
double rxdd = rxd * rxd;
double rydd = ryd * ryd;
double r1x = r1 * r1;
double r2y = r2 * r2;
double lamda = rxdd / r1x + rydd / r2y;
double sds;
if (lamda > 1)
{
r1 = Math.Sqrt(lamda) * r1;
r2 = Math.Sqrt(lamda) * r2;
sds = 0;
}
else
{
double seif = 1;
if (largeArcFlag == fS)
{
seif = -1;
}
sds = seif * Math.Sqrt((r1x * r2y - r1x * rydd - r2y * rxdd) / (r1x * rydd + r2y * rxdd));
}
double txd = sds * r1 * ryd / r2;
double tyd = -1 * sds * r2 * rxd / r1;
double tx = cpsi * txd - spsi * tyd + x / 2;
double ty = spsi * txd + cpsi * tyd + y / 2;
double rad = Math.Atan2((ryd - tyd) / r2, (rxd - txd) / r1) - Math.Atan2(0, 1);
double s1 = (rad >= 0) ? rad : 2 * Math.PI + rad;
rad = Math.Atan2((-ryd - tyd) / r2, (-rxd - txd) / r1) - Math.Atan2((ryd - tyd) / r2, (rxd - txd) / r1);
double dr = (rad >= 0) ? rad : 2 * Math.PI + rad;
if (fS == 0 && dr > 0)
{
dr -= 2 * Math.PI;
}
else if (fS != 0 && dr < 0)
{
dr += 2 * Math.PI;
}
double sse = dr * 2 / Math.PI;
int seg = (int)Math.Ceiling(sse < 0 ? -1 * sse : sse);
double segr = dr / seg;
double t = 8 / 3 * Math.Sin(segr / 4) * Math.Sin(segr / 4) / Math.Sin(segr / 2);
double cpsir1 = cpsi * r1;
double cpsir2 = cpsi * r2;
double spsir1 = spsi * r1;
double spsir2 = spsi * r2;
double mc = Math.Cos(s1);
double ms = Math.Sin(s1);
double x2 = -t * (cpsir1 * ms + spsir2 * mc);
double y2 = -t * (spsir1 * ms - cpsir2 * mc);
double x3 = 0;
double y3 = 0;
double[] result = new double[seg * 6];
for (int n = 0; n < seg; ++n)
{
s1 += segr;
mc = Math.Cos(s1);
ms = Math.Sin(s1);
x3 = cpsir1 * mc - spsir2 * ms + tx;
y3 = spsir1 * mc + cpsir2 * ms + ty;
double dx = -t * (cpsir1 * ms + spsir2 * mc);
double dy = -t * (spsir1 * ms - cpsir2 * mc);
// CurveTo updates x0, y0 so need to restore it
int index = n * 6;
result[index] = x2 + x0;
result[index + 1] = y2 + y0;
result[index + 2] = x3 - dx + x0;
result[index + 3] = y3 - dy + y0;
result[index + 4] = x3 + x0;
result[index + 5] = y3 + y0;
x2 = x3 + dx;
y2 = y3 + dy;
}
return result;
}
///
/// Returns the bounding box of the rotated rectangle.
///
public static mxRectangle GetBoundingBox(mxRectangle rect, double rotation)
{
// TODO: Check use of GraphicsPath (see mxGdiCanvas.DrawText)
mxRectangle result = null;
if (rect != null && rotation != 0)
{
double rad = ToRadians(rotation);
double cos = Math.Cos(rad);
double sin = Math.Sin(rad);
mxPoint cx = new mxPoint(rect.X + rect.Width / 2,
rect.Y + rect.Height / 2);
mxPoint p1 = new mxPoint(rect.X, rect.Y);
mxPoint p2 = new mxPoint(rect.X + rect.Width, rect.Y);
mxPoint p3 = new mxPoint(p2.X, rect.Y + rect.Height);
mxPoint p4 = new mxPoint(rect.X, p3.Y);
p1 = GetRotatedPoint(p1, cos, sin, cx);
p2 = GetRotatedPoint(p2, cos, sin, cx);
p3 = GetRotatedPoint(p3, cos, sin, cx);
p4 = GetRotatedPoint(p4, cos, sin, cx);
result = new mxRectangle((int)p1.X, (int)p1.Y, 0,
0);
result.Add(new mxRectangle(p2.X, p2.Y, 0, 0));
result.Add(new mxRectangle(p3.X, p3.Y, 0, 0));
result.Add(new mxRectangle(p4.X, p4.Y, 0, 0));
}
return result;
}
///
/// Rotates the given point by the given cos and sin.
///
public static mxPoint GetRotatedPoint(mxPoint pt, double cos, double sin)
{
return GetRotatedPoint(pt, cos, sin, new mxPoint());
}
///
/// Rotates the given point by the given cos and sin.
///
public static mxPoint GetRotatedPoint(mxPoint pt, double cos, double sin,
mxPoint c)
{
double x = pt.X - c.X;
double y = pt.Y - c.Y;
double x1 = x * cos - y * sin;
double y1 = y * cos + x * sin;
return new mxPoint(x1 + c.X, y1 + c.Y);
}
///
///
///
///
///
///
///
///
///
public static void FillClippedRect(Graphics g, Brush brush, int x, int y, int width, int height)
{
RectangleF bg = new RectangleF(x, y, width, height);
if (g.ClipBounds != null)
{
bg.Intersect(g.ClipBounds);
}
g.FillRectangle(brush, bg.X, bg.Y, bg.Width, bg.Height);
}
///
/// Creates an image for the given parameters.
///
///
///
///
///
public static Image CreateImage(int width, int height, Color? background)
{
Image image = new Bitmap(width, height);
Graphics g = Graphics.FromImage(image);
if (background != null)
{
g.FillRectangle(new SolidBrush((Color)background),
0, 0, width, height);
}
else
{
g.Clear(Color.Transparent);
}
return image;
}
///
/// Creates a new list of new points obtained by translating the points in
/// the given list by the given vector. Elements that are not mxPoints are
/// added to the result as-is.
///
///
///
///
///
public static List TranslatePoints(List pts, double dx, double dy)
{
List result = null;
if (pts != null)
{
result = new List(pts.Count);
foreach (mxPoint point in pts)
{
mxPoint pt = point.Clone();
pt.X += dx;
pt.Y += dy;
result.Add(pt);
}
}
return result;
}
///
/// Returns the intersection of two lines as an mxPoint.
///
/// X-coordinate of the first line's startpoint.
/// Y-coordinate of the first line's startpoint.
/// X-coordinate of the first line's endpoint.
/// Y-coordinate of the first line's endpoint.
/// X-coordinate of the second line's startpoint.
/// Y-coordinate of the second line's startpoint.
/// X-coordinate of the second line's endpoint.
/// Y-coordinate of the second line's endpoint.
///
public static mxPoint Intersection(double x0, double y0, double x1,
double y1, double x2, double y2, double x3, double y3)
{
double denom = ((y3 - y2) * (x1 - x0)) - ((x3 - x2) * (y1 - y0));
double nume_a = ((x3 - x2) * (y0 - y2)) - ((y3 - y2) * (x0 - x2));
double nume_b = ((x1 - x0) * (y0 - y2)) - ((y1 - y0) * (x0 - x2));
double ua = nume_a / denom;
double ub = nume_b / denom;
if (ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0)
{
// Get the intersection point
double intersectionX = x0 + ua * (x1 - x0);
double intersectionY = y0 + ua * (y1 - y0);
return new mxPoint(intersectionX, intersectionY);
}
// No intersection
return null;
}
///
/// Returns the stylename in a style of the form stylename[;key=value] or an
/// empty string if the given style does not contain a stylename.
///
/// String of the form stylename[;key=value].
/// Returns the stylename from the given formatted string.
public static String GetStylename(String style)
{
if (style != null)
{
String[] pairs = style.Split(';');
String stylename = pairs[0];
if (stylename.IndexOf("=") < 0)
{
return stylename;
}
}
return "";
}
///
/// Returns the stylenames in a style of the form stylename[;key=value] or an
/// empty array if the given style does not contain any stylenames.
///
/// String of the form stylename[;stylename][;key=value].
/// Returns the stylename from the given formatted string.
public static String[] GetStylenames(String style)
{
ArrayList result = new ArrayList();
if (style != null)
{
String[] pairs = style.Split(';');
for (int i = 0; i < pairs.Length; i++)
{
if (pairs[i].IndexOf("=") < 0)
{
result.Add(pairs[i]);
}
}
}
return (String[]) result.ToArray();
}
///
/// Returns the index of the given stylename in the given style. This
/// returns -1 if the given stylename does not occur (as a stylename) in the
/// given style, otherwise it returns the index of the first character.
///
///
///
///
public static int IndexOfStylename(String style, String stylename)
{
if (style != null && stylename != null)
{
String[] tokens = style.Split(';');
int pos = 0;
for (int i = 0; i < tokens.Length; i++)
{
if (tokens[i].Equals(stylename))
{
return pos;
}
pos += tokens[i].Length + 1;
}
}
return -1;
}
///
/// Adds the specified stylename to the given style if it does not already
/// contain the stylename.
///
///
///
///
public String AddStylename(String style, String stylename)
{
if (IndexOfStylename(style, stylename) < 0)
{
if (style == null)
{
style = "";
}
else if (style.Length > 0 && style[style.Length] != ';')
{
style += ';';
}
style += stylename;
}
return style;
}
///
/// Removes all occurrences of the specified stylename in the given style
/// and returns the updated style.
///
///
///
///
public String RemoveStylename(String style, String stylename)
{
StringBuilder buffer = new StringBuilder();
if (style != null)
{
String[] tokens = style.Split(';');
for (int i = 0; i < tokens.Length; i++)
{
if (!tokens[i].Equals(stylename))
{
buffer.Append(tokens[i] + ";");
}
}
}
String result = buffer.ToString();
return (result.Length > 1) ? result.Substring(0, result.Length - 1)
: result;
}
///
/// Removes all stylenames from the given style and returns the updated
/// style.
///
///
///
public static String RemoveAllStylenames(String style)
{
StringBuilder buffer = new StringBuilder();
if (style != null)
{
String[] tokens = style.Split(';');
for (int i = 0; i < tokens.Length; i++)
{
if (tokens[i].IndexOf('=') >= 0)
{
buffer.Append(tokens[i] + ";");
}
}
}
String result = buffer.ToString();
return (result.Length > 1) ? result.Substring(0, result.Length - 1)
: result;
}
///
/// Assigns the value for the given key in the styles of the given cells, or
/// removes the key from the styles if the value is null.
///
/// Model to execute the transaction in.
/// Array of cells to be updated.
/// Key of the style to be changed.
/// New value for the given key.
public static void SetCellStyles(mxIGraphModel model, Object[] cells, String key, String value)
{
if (cells != null && cells.Length > 0)
{
model.BeginUpdate();
try
{
for (int i = 0; i < cells.Length; i++)
{
if (cells[i] != null)
{
String style = SetStyle(
model.GetStyle(cells[i]),
key, value);
model.SetStyle(cells[i], style);
}
}
}
finally
{
model.EndUpdate();
}
}
}
///
/// Adds or removes the given key, value pair to the style and returns the
/// new style. If value is null or zero length then the key is removed from
/// the style.
///
/// String of the form stylename[;key=value].
/// Key of the style to be changed.
/// New value for the given key.
/// Returns the new style.
public static String SetStyle(String style, String key, String value)
{
bool isValue = value != null && value.Length > 0;
if (style == null || style.Length == 0)
{
if (isValue)
{
style = key + "=" + value;
}
}
else
{
int index = style.IndexOf(key + "=");
if (index < 0)
{
String sep = (style.EndsWith(";")) ? "" : ";";
if (isValue)
{
style = style + sep + key + '=' + value;
}
else
{
style = style + sep + key + "=0";
}
}
else
{
String tmp = (isValue) ? key + "=" + value : "";
int cont = style.IndexOf(";", index);
if (!isValue)
{
cont++;
}
style = style.Substring(0, index) + tmp +
((cont > index) ? style.Substring(cont) : "");
}
}
return style;
}
///
/// Sets or toggles the flag bit for the given key in the cell's styles.
/// If value is null then the flag is toggled.
///
/// Model that contains the cells.
/// Array of cells to change the style for.
/// Key of the style to be changed.
/// Integer for the bit to be changed.
/// Optional boolean value for the flag.
public static void SetCellStyleFlags(mxIGraphModel model, Object[] cells, String key, int flag, Boolean value)
{
if (cells != null && cells.Length > 0)
{
model.BeginUpdate();
try
{
for (int i = 0; i < cells.Length; i++)
{
if (cells[i] != null)
{
String style = SetStyleFlag(
model.GetStyle(cells[i]),
key, flag, value);
model.SetStyle(cells[i], style);
}
}
}
finally
{
model.EndUpdate();
}
}
}
///
/// Sets or removes the given key from the specified style and returns the
/// new style. If value is null then the flag is toggled.
///
/// String of the form stylename[;key=value].
/// Key of the style to be changed.
/// Integer for the bit to be changed.
/// Optional boolean value for the given flag.
/// Returns the new style.
public static String SetStyleFlag(String style, String key, int flag, bool? value)
{
if (style == null || style.Length == 0)
{
if (value == null || (bool)value)
{
style = key + "=" + flag;
}
else
{
style = key + "=0";
}
}
else
{
int index = style.IndexOf(key + '=');
if (index < 0)
{
if (value == null || (bool) value)
{
String sep = (style.EndsWith(";")) ? "" : ";";
style = style + sep + key + "=" + flag;
}
}
else
{
int cont = style.IndexOf(";", index);
String tmp = "";
int result = 0;
if (cont < 0)
{
tmp = style.Substring(index + key.Length + 1);
}
else
{
tmp = style.Substring(index + key.Length + 1, cont);
}
if (value == null)
{
result = int.Parse(tmp) ^ flag;
}
else if ((bool) value)
{
result = int.Parse(tmp) | flag;
}
else
{
result = int.Parse(tmp) & ~flag;
}
style = style.Substring(0, index) + key + "=" + result +
((cont >= 0) ? style.Substring(cont) : "");
}
}
return style;
}
///
/// Returns true if the dictionary contains true for the given key or
/// false if no value is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Returns the boolean value for key in dict.
public static bool IsTrue(Dictionary dict, string key)
{
return IsTrue(dict, key, false);
}
///
/// Returns true if the dictionary contains true for the given key or the
/// given default value if no value is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Default value to return if the key is undefined.
/// Returns the boolean value for key in dict.
public static bool IsTrue(Dictionary dict, string key, bool defaultValue)
{
object value = null;
dict.TryGetValue(key, out value);
if (value == null)
{
return defaultValue;
}
else
{
return value.Equals("1") || value.ToString().ToLower().Equals("true");
}
}
///
/// Returns the value for key in dictionary as an int or 0 if no value is
/// defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Returns the integer value for key in dict.
public static int GetInt(Dictionary dict, string key)
{
return GetInt(dict, key, 0);
}
///
/// Returns the value for key in dictionary as an int or the given default
/// value if no value is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Default value to return if the key is undefined.
/// Returns the integer value for key in dict.
public static int GetInt(Dictionary dict, string key, int defaultValue)
{
object value = null;
dict.TryGetValue(key, out value);
if (value == null)
{
return defaultValue;
}
else
{
return int.Parse(value.ToString());
}
}
///
/// Returns the value for key in dictionary as a float or 0 if no value is
/// defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Returns the float value for key in dict.
public static float GetFloat(Dictionary dict, string key)
{
return GetFloat(dict, key, 0);
}
///
/// Returns the value for key in dictionary as a float or the given default
/// value if no value is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Default value to return if the key is undefined.
/// Returns the float value for key in dict.
public static float GetFloat(Dictionary dict, string key, float defaultValue)
{
object value = null;
dict.TryGetValue(key, out value);
if (value == null)
{
return defaultValue;
}
else
{
return float.Parse(value.ToString());
}
}
///
/// Returns the value for key in dictionary as a double or 0 if no value is
/// defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Returns the double value for key in dict.
public static double GetDouble(Dictionary dict, string key)
{
return GetDouble(dict, key, 0);
}
///
/// Returns the value for key in dictionary as a double or the given default
/// value if no value is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Default value to return if the key is undefined.
/// Returns the double value for key in dict.
public static double GetDouble(Dictionary dict, string key, double defaultValue)
{
object value = null;
dict.TryGetValue(key, out value);
if (value == null)
{
return defaultValue;
}
else
{
return double.Parse(value.ToString());
}
}
///
/// Returns the value for key in dictionary as a string or null if no value
/// is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Returns the string value for key in dict.
public static string GetString(Dictionary dict, string key)
{
return GetString(dict, key, null);
}
///
/// Returns the value for key in dictionary as a string or the given default
/// value if no value is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Default value to return if the key is undefined.
/// Returns the string value for key in dict.
public static string GetString(Dictionary dict, string key, string defaultValue)
{
object value = null;
dict.TryGetValue(key, out value);
if (value == null)
{
return defaultValue;
}
else
{
return value.ToString();
}
}
///
/// Returns the value for key in dictionary as a color or null if no value
/// is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Returns the color value for key in dict.
public static Color? GetColor(Dictionary dict, string key)
{
return GetColor(dict, key, null);
}
///
/// Returns the value for key in dictionary as a color or the given default
/// value if no value is defined for the key.
///
/// Dictionary that contains the key, value pairs.
/// Key whose value should be returned.
/// Default value to return if the key is undefined.
/// Returns the color value for key in dict.
public static Color? GetColor(Dictionary dict, string key, Color? defaultValue)
{
object value = null;
dict.TryGetValue(key, out value);
if (value == null)
{
return defaultValue;
}
else
{
if (value.ToString().Equals("none"))
{
return null;
}
return ColorTranslator.FromHtml(value.ToString());
}
}
///
///
///
///
///
///
public static Font GetFont(Dictionary style)
{
return GetFont(style, 1);
}
///
///
///
///
///
///
public static Font GetFont(Dictionary style, double scale)
{
float fontSize = (float)(GetDouble(style, mxConstants.STYLE_FONTSIZE, mxConstants.DEFAULT_FONTSIZE) * scale);
string fontFamily = GetString(style, mxConstants.STYLE_FONTFAMILY, mxConstants.DEFAULT_FONTFAMILY);
int fontStyle = GetInt(style, mxConstants.STYLE_FONTSTYLE);
FontStyle tmp = ((fontStyle & mxConstants.FONT_BOLD) == mxConstants.FONT_BOLD) ? FontStyle.Bold
: FontStyle.Regular;
tmp |= ((fontStyle & mxConstants.FONT_ITALIC) == mxConstants.FONT_ITALIC) ? FontStyle.Italic
: FontStyle.Regular;
tmp |= ((fontStyle & mxConstants.FONT_UNDERLINE) == mxConstants.FONT_UNDERLINE) ? FontStyle.Underline
: FontStyle.Regular;
return new Font(fontFamily, (float)(fontSize * mxConstants.FONT_SIZEFACTOR), tmp);
}
///
/// Creates a new StringFormat object for the given style.
///
///
///
public static StringFormat GetStringFormat(Dictionary style)
{
StringFormat format = new StringFormat(StringFormatFlags.NoClip);
format.Trimming = StringTrimming.None;
// This is not required as the rectangle for the text will take this flag into account.
// However, we want to avoid any possible word-wrap unless explicitely specified.
if (!mxUtils.GetString(style, mxConstants.STYLE_WHITE_SPACE, "").Equals("wrap"))
{
format.FormatFlags |= StringFormatFlags.NoWrap;
}
// Sets the horizontal alignment
string align = GetString(style, mxConstants.STYLE_ALIGN);
if (align == null || align.Equals(mxConstants.ALIGN_CENTER))
{
format.Alignment = StringAlignment.Center;
}
else if (align.Equals(mxConstants.ALIGN_LEFT))
{
format.Alignment = StringAlignment.Near;
}
else if (align.Equals(mxConstants.ALIGN_RIGHT))
{
format.Alignment = StringAlignment.Far;
}
// Sets the vertical alignment
string vAlign = GetString(style, mxConstants.STYLE_VERTICAL_ALIGN);
if (vAlign == null || vAlign.Equals(mxConstants.ALIGN_MIDDLE))
{
format.LineAlignment = StringAlignment.Center;
}
else if (vAlign.Equals(mxConstants.ALIGN_TOP))
{
format.LineAlignment = StringAlignment.Near;
}
else if (vAlign.Equals(mxConstants.ALIGN_BOTTOM))
{
format.LineAlignment = StringAlignment.Far;
}
return format;
}
///
/// Reads the given filename into a string.
///
/// Name of the file to be read.
/// Returns a string representing the file contents.
public static string ReadFile(string filename)
{
return File.ReadAllText(filename);
}
///
/// Returns the Md5 hash for the given text.
///
/// String whose Md5 hash should be returned.
/// Returns the Md5 hash for the given text.
public static string GetMd5Hash(string text)
{
MD5 md5Hasher = new MD5CryptoServiceProvider();
byte[] data = md5Hasher.ComputeHash(Encoding.ASCII.GetBytes(text));
return Convert.ToBase64String(data);
}
///
/// Returns true if the given value is an XML node with the specified nodename.
/// specified.
///
/// Object that represents the value to be tested.
/// String that specifies the node name.
/// Returns true if the node name of the user object is equal to the
/// given type.
public static bool IsNode(Object value, String nodeName)
{
return IsNode(value, nodeName, null, null);
}
///
/// Returns true if the user object is an XML node with the specified type
/// and and the optional attribute has the specified value or is not
/// specified.
///
/// Object that represents the value to be tested.
/// String that specifies the node name.
/// Optional attribute name to check.
/// Optional attribute value to check.
/// Returns true if the cell matches the given conditions.
public static bool IsNode(Object value, String nodeName, String attributeName, String attributeValue)
{
if (value is XmlElement)
{
XmlElement element = (XmlElement)value;
if (String.Compare(element.Name, attributeName, true) == 0)
{
return attributeName == null ||
String.Compare(element.GetAttribute(attributeName),
attributeValue, true) == 0;
}
}
return false;
}
///
/// Loads an image from the local filesystem, a data URI or any other URL.
///
public static Image LoadImage(String url)
{
Image img = null;
if (url != null)
{
try
{
img = Image.FromFile(url);
}
catch (Exception)
{
Stream stream = null;
// Parses data URIs of the form data:image/format;base64,xxx
if (url.StartsWith("data:image/"))
{
int comma = url.IndexOf(',');
byte[] data = Convert.FromBase64String(url.Substring(comma + 1));
stream = new MemoryStream(data);
}
else
{
try
{
WebClient wc = new WebClient();
stream = wc.OpenRead(url);
}
catch (Exception)
{
// ignore
}
}
if (stream != null)
{
try
{
img = Image.FromStream(stream);
}
catch (Exception e)
{
// ignore
}
}
}
}
return img;
}
///
/// Returns a new, empty DOM document. External entities and DTDs are ignored.
///
/// Returns a new DOM document.
public static XmlDocument CreateDocument()
{
XmlDocument document = new XmlDocument();
document.XmlResolver = null;
return document;
}
///
/// Returns a new DOM document for the given URI.
///
/// URI to parse into the document.
/// Returns a new DOM document for the given URI.
public static XmlDocument LoadDocument(string uri)
{
XmlDocument doc = CreateDocument();
doc.Load(uri);
return doc;
}
///
/// Returns a document that represents the given XML string.
///
/// String that contains the XML markup.
/// Returns an XML document.
public static XmlDocument ParseXml(string xml)
{
XmlDocument doc = CreateDocument();
doc.LoadXml(xml);
return doc;
}
///
/// Returns the first node where attr equals value.
/// This implementation does not use XPath.
///
public static XmlNode FindNode(XmlNode node, String attr, String value)
{
Object tmp = node.Attributes[attr];
if (tmp != null &&
tmp.ToString().Equals(value))
{
return node;
}
node = node.FirstChild;
while (node != null)
{
XmlNode result = FindNode(node, attr, value);
if (result != null)
{
return result;
}
node = node.NextSibling;
}
return null;
}
///
/// Evaluates a Java expression to a class member using mxCodecRegistry.
/// The range of supported expressions is limited to static class
/// members such as mxEdgeStyle.ElbowConnector.
///
///
///
public static Object Eval(string expression)
{
int dot = expression.LastIndexOf(".");
if (dot > 0)
{
Type type = mxCodecRegistry.GetTypeForName(expression.Substring(0, dot));
if (type != null)
{
try
{
return type.GetField(expression.Substring(dot + 1)).GetValue(null);
}
catch (Exception e)
{
Trace.WriteLine("mxUtils.Eval(" + expression + "): " + e.Message);
}
}
}
return expression;
}
///
/// Converts the ampersand, quote, prime, less-than and greater-than characters
/// to their corresponding HTML entities in the given string.
///
///
///
public static String HtmlEntities(String text)
{
return text.Replace("&", "&").Replace("\"", """)
.Replace("'", "′").Replace("<", "<").Replace(
">", ">");
}
///
/// Returns a string that represents the given node.
///
/// Node to return the XML for.
/// Returns an XML string.
public static string GetXml(XmlNode node)
{
return GetXml(node, Formatting.None);
}
///
/// Returns a pretty-printed XML string for the given node.
///
/// Node to return the XML for.
/// Returns a formatted XML string.
public static string GetPrettyXml(XmlNode node)
{
return GetXml(node, Formatting.Indented);
}
///
/// Returns a pretty-printed XML string for the given node.
///
/// Node to return the XML for.
/// Formatting of the string to be returned.
/// Returns a formatted XML string.
public static string GetXml(XmlNode node, Formatting formatting)
{
StringWriter stringWriter = new StringWriter();
XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter);
xmlTextWriter.Formatting = formatting;
node.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
return stringWriter.ToString();
}
}
}