/// <summary> /// Draws grid lines corresponding to a vertical scale using GDI+</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="majorSpacing">Spacing, in pixels, between major tick marks</param> /// <param name="linePen">Grid line pen</param> /// <param name="g">Graphics GDI+ drawing surface</param> public static void DrawVerticalScaleGrid( Matrix transform, RectangleF graphRect, int majorSpacing, Pen linePen, System.Drawing.Graphics g) { double xScale = transform.Elements[0]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double min = Math.Min(graphRect.Left, graphRect.Right); double max = Math.Max(graphRect.Left, graphRect.Right); double tickAnchor = D2dUtil.CalculateTickAnchor(min, max); double step = D2dUtil.CalculateStep(min, max, Math.Abs(clientRect.Right - clientRect.Left), majorSpacing, 0.0); if (step > 0) { double offset = tickAnchor - min; offset = offset - MathUtil.Remainder(offset, step) + step; for (double x = tickAnchor - offset; x <= max; x += step) { double cx = (x - graphRect.Left) * xScale + clientRect.Left; g.DrawLine(linePen, (float)cx, clientRect.Top, (float)cx, clientRect.Bottom); } } }
/// <summary> /// Draws grid lines corresponding to a horizontal scale using GDI+</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="majorSpacing">Spacing, in pixels, between major tick marks</param> /// <param name="linePen">Grid line pen</param> /// <param name="g">Graphics GDI+ drawing surface</param> public static void DrawHorizontalScaleGrid( Matrix transform, RectangleF graphRect, int majorSpacing, Pen linePen, System.Drawing.Graphics g) { double yScale = transform.Elements[3]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double min = Math.Min(graphRect.Top, graphRect.Bottom); double max = Math.Max(graphRect.Top, graphRect.Bottom); double tickAnchor = D2dUtil.CalculateTickAnchor(min, max); double step = D2dUtil.CalculateStep(min, max, Math.Abs(clientRect.Bottom - clientRect.Top), majorSpacing, 0.0); if (step > 0) { double offset = tickAnchor - min; offset = offset - MathUtil.Remainder(offset, step) + step; for (double y = tickAnchor - offset; y <= max; y += step) { double cy; if (yScale > 0) { cy = (y - min) * yScale + clientRect.Top; } else { cy = (y - max) * yScale + clientRect.Top; } g.DrawLine(linePen, clientRect.Left, (float)cy, clientRect.Right, (float)cy); } } }
/// <summary> /// Gets a registered 32 x 32 image, given an ID</summary> /// <param name="id">Image identifier</param> /// <returns>Registered image, or scaled image, or null if not found</returns> public static Image GetImage32(string id) { Image image = s_images32.Images[id]; if (image == null) { image = GetImage(id); if (image != null) { image = GdiUtil.ResizeImage(image, 32); } } return(image); }
/// <summary> /// Gets a registered 32 x 32 image, given an ID</summary> /// <param name="id">Image identifier</param> /// <returns>Registered image, or scaled image, or null if not found</returns> public static Image GetImage32(string id) { if (string.IsNullOrEmpty(id)) { throw new ArgumentNullException("Image id is null. Call Sce.Atf.WinForms.Resources.Register() to force registration of image resources."); } Image image = s_images32.Images[id]; if (image == null) { image = GetImage(id); if (image != null) { image = GdiUtil.ResizeImage(image, 32); } } return(image); }
private static void RegisterImage( Assembly resourceAssembly, string name1, string name2, string name3) { if (name1 != null) { if (name2 == null || name3 == null) { RegisterImage(name1, GdiUtil.GetImage(resourceAssembly, name1)); } else { RegisterImage( name1, GdiUtil.GetImage(resourceAssembly, name1), GdiUtil.GetImage(resourceAssembly, name2), GdiUtil.GetImage(resourceAssembly, name3)); } } }
/// <summary> /// Labels junctions on a grid background using GDI+</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="step">Grid step in canvas coordinates</param> /// <param name="font">Font</param> /// <param name="textBrush">Text brush</param> /// <param name="g">Graphics GDI+ drawing surface</param> public static void LabelGrid( Matrix transform, RectangleF graphRect, double step, Font font, Brush textBrush, System.Drawing.Graphics g) { double xScale = transform.Elements[0]; double yScale = transform.Elements[3]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double screenStep = Math.Min(Math.Abs(xScale * step), Math.Abs(yScale * step)); const int MIN_LABEL_SPACING = 96; while (screenStep < MIN_LABEL_SPACING) { screenStep *= 2; step *= 2; } double xStart = graphRect.Left - MathUtil.Remainder(graphRect.Left, step); double yStart = graphRect.Top - MathUtil.Remainder(graphRect.Top, step); for (double y = yStart; y <= graphRect.Bottom; y += step) { double cy = (y - graphRect.Top) * yScale + clientRect.Top; string yString = String.Format("{0:G4}", y); for (double x = xStart; x <= graphRect.Right; x += step) { double cx = (x - graphRect.Left) * xScale + clientRect.Left; string xyString = String.Format("({0:G4}, " + yString + ")", x); g.DrawString(xyString, font, textBrush, (float)cx, (float)cy); } } }
/// <summary> /// Draws vertical grid lines using GDI+</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="step">Grid step in canvas coordinates</param> /// <param name="color">Grid line color</param> /// <param name="g">Graphics GDI+ drawing surface</param> public static void DrawVerticalGrid( Matrix transform, RectangleF graphRect, double step, Color color, System.Drawing.Graphics g) { double xScale = transform.Elements[0]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double screenStep = Math.Abs(xScale * step); Pen pen = CreateFadedPen(screenStep, color); double start = graphRect.Left - MathUtil.Remainder(graphRect.Left, step) + step; for (double x = start; x < graphRect.Right; x += step) { double cx = (x - graphRect.Left) * xScale + clientRect.Left; g.DrawLine(pen, (float)cx, clientRect.Top, (float)cx, clientRect.Bottom); } pen.Dispose(); }
/// <summary> /// Draws horizontal grid using Direct2D</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="step">Grid step in canvas coordinates</param> /// <param name="color">Grid line color</param> /// <param name="g">Graphics Direct2D drawing surface</param> public static void DrawHorizontalGrid( Matrix transform, RectangleF graphRect, double step, Color color, D2dGraphics g) { double yScale = transform.Elements[3]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double screenStep = Math.Abs(yScale * step); int a = ComputeOpacity(screenStep); color = Color.FromArgb(a, color); double start = graphRect.Top - MathUtil.Remainder(graphRect.Top, step) + step; for (double y = start; y < graphRect.Bottom; y += step) { double cy = (y - graphRect.Top) * yScale + clientRect.Top; g.DrawLine(clientRect.Left, (float)cy, clientRect.Right, (float)cy, color); } }
/// <summary> /// Draws horizontal grid lines using GDI+</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="step">Grid step in canvas coordinates</param> /// <param name="color">Grid line color</param> /// <param name="g">Graphics GDI+ drawing surface</param> public static void DrawHorizontalGrid( Matrix transform, RectangleF graphRect, double step, Color color, System.Drawing.Graphics g) { double yScale = transform.Elements[3]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double screenStep = Math.Abs(yScale * step); Pen pen = CreateFadedPen(screenStep, color); double start = graphRect.Top - MathUtil.Remainder(graphRect.Top, step) + step; for (double y = start; y < graphRect.Bottom; y += step) { double cy = (y - graphRect.Top) * yScale + clientRect.Top; g.DrawLine(pen, clientRect.Left, (float)cy, clientRect.Right, (float)cy); } pen.Dispose(); }
/// <summary> /// Draws vertical grid lines using Direct2D</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="step">Grid step in canvas coordinates</param> /// <param name="color">Grid line color</param> /// <param name="g">Graphics Direct2D drawing surface</param> public static void DrawVerticalGrid( Matrix transform, RectangleF graphRect, double step, Color color, D2dGraphics g) { double xScale = transform.Elements[0]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double screenStep = Math.Abs(xScale * step); int a = ComputeOpacity(screenStep); color = Color.FromArgb(a, color); double start = graphRect.Left - MathUtil.Remainder(graphRect.Left, step) + step; for (double x = start; x < graphRect.Right; x += step) { double cx = (x - graphRect.Left) * xScale + clientRect.Left; g.DrawLine((float)cx, clientRect.Top, (float)cx, clientRect.Bottom, color); } }
/// <summary> /// Draws a vertical chart scale using GDI+</summary> /// <param name="transform">Transform from graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="left">Scale left</param> /// <param name="majorSpacing">Spacing, in pixels, between major tick marks</param> /// <param name="minimumGraphStep">Minimum spacing, in graph (world) space, between ticks. /// For example, 1.0 would limit ticks to being drawn on whole integers.</param> /// <param name="linePen">Scale line pen</param> /// <param name="font">Scale font</param> /// <param name="textBrush">Text brush</param> /// <param name="g">Graphics GDI+ drawing surface</param> public static void DrawVerticalScale( Matrix transform, RectangleF graphRect, bool left, int majorSpacing, float minimumGraphStep, Pen linePen, Font font, Brush textBrush, System.Drawing.Graphics g) { double yScale = transform.Elements[3]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double tickEnd, minorTickStart, textStart; Matrix temp = g.Transform.Clone(); Matrix vertical = g.Transform; vertical.Translate(clientRect.Right, clientRect.Bottom); vertical.Rotate(90); vertical.Translate(-clientRect.Left, -clientRect.Top); g.Transform = vertical; if (left) { tickEnd = clientRect.Right - clientRect.X; minorTickStart = tickEnd - 6; textStart = tickEnd - 19; } else { tickEnd = clientRect.Left + 1; minorTickStart = tickEnd + 6; textStart = tickEnd + 8; } double min = Math.Min(graphRect.Top, graphRect.Bottom); double max = Math.Max(graphRect.Top, graphRect.Bottom); double tickAnchor = D2dUtil.CalculateTickAnchor(min, max); double majorGraphStep = D2dUtil.CalculateStep( min, max, Math.Abs(clientRect.Bottom - clientRect.Top), majorSpacing, minimumGraphStep); int numMinorTicks = D2dUtil.CalculateNumMinorTicks(majorGraphStep, minimumGraphStep, 5); double cMinorStep = (majorGraphStep / numMinorTicks) * yScale; if (majorGraphStep > 0) { double offset = tickAnchor - min; offset = offset - MathUtil.Remainder(offset, majorGraphStep) + majorGraphStep; for (double x = tickAnchor - offset; x <= max; x += majorGraphStep) { double cx = (x - min) * yScale + clientRect.Left; //g.DrawLine(linePen, (float)cx, (float)majorTickStart, (float)cx, (float)tickEnd); // draw minor ticks double cmx = cx; for (int i = 0; i < numMinorTicks; i++) { cmx += cMinorStep; g.DrawLine(linePen, (float)cmx, (float)minorTickStart, (float)cmx, (float)tickEnd); } string xString = String.Format("{0:G8}", Math.Round(x, 6)); g.DrawString(xString, font, textBrush, (float)cx + 2, (float)textStart); } } g.Transform = temp; }
/// <summary> /// Draws a horizontal chart scale using GDI+</summary> /// <param name="transform">Graph (world) to Window's client (screen) transform</param> /// <param name="graphRect">Graph rectangle</param> /// <param name="top">Whether the scale should be aligned along the top of the rectangle</param> /// <param name="majorSpacing">Spacing, in pixels, between major tick marks</param> /// <param name="minimumGraphStep">Minimum spacing, in graph (world) space, between ticks. /// For example, 1.0 would limit ticks to being drawn on whole integers.</param> /// <param name="linePen">Scale line pen</param> /// <param name="font">Scale font</param> /// <param name="textBrush">Text brush</param> /// <param name="g">Graphics GDI+ drawing surface</param> public static void DrawHorizontalScale( Matrix transform, RectangleF graphRect, bool top, int majorSpacing, float minimumGraphStep, Pen linePen, Font font, Brush textBrush, System.Drawing.Graphics g) { double xScale = transform.Elements[0]; RectangleF clientRect = GdiUtil.Transform(transform, graphRect); double tickEnd, majorTickStart, minorTickStart, textStart; if (top) { tickEnd = clientRect.Top + 1; majorTickStart = tickEnd + 12; minorTickStart = tickEnd + 6; textStart = tickEnd + 8; } else { tickEnd = clientRect.Bottom - 1; majorTickStart = tickEnd - 12; minorTickStart = tickEnd - 6; textStart = tickEnd - 19; } double min = Math.Min(graphRect.Left, graphRect.Right); double max = Math.Max(graphRect.Left, graphRect.Right); double tickAnchor = D2dUtil.CalculateTickAnchor(min, max); double majorGraphStep = D2dUtil.CalculateStep( min, max, Math.Abs(clientRect.Right - clientRect.Left), majorSpacing, minimumGraphStep); int numMinorTicks = D2dUtil.CalculateNumMinorTicks(majorGraphStep, minimumGraphStep, 5); double cMinorStep = (majorGraphStep / numMinorTicks) * xScale; if (majorGraphStep > 0) { double offset = tickAnchor - min; offset = offset - MathUtil.Remainder(offset, majorGraphStep); // draw leading minor ticks double cmx; cmx = ((tickAnchor - (offset + majorGraphStep)) - min) * xScale + clientRect.Left + cMinorStep; for (int i = 0; i < numMinorTicks - 1 && cmx < clientRect.Right; i++) { // cull minor ticks outside of the view if (cmx > clientRect.Left) { g.DrawLine(linePen, (float)cmx, (float)minorTickStart, (float)cmx, (float)tickEnd); } cmx += cMinorStep; } for (double x = tickAnchor - offset; x < max; x += majorGraphStep) { double cx = (x - min) * xScale + clientRect.Left; g.DrawLine(linePen, (float)cx, (float)majorTickStart, (float)cx, (float)tickEnd); string xString = String.Format("{0:G8}", Math.Round(x, 6)); g.DrawString(xString, font, textBrush, (float)cx + 1, (float)textStart); // draw minor ticks cmx = cx + cMinorStep; for (int i = 0; i < numMinorTicks - 1 && cmx < clientRect.Right; i++) { g.DrawLine(linePen, (float)cmx, (float)minorTickStart, (float)cmx, (float)tickEnd); cmx += cMinorStep; } } } }
/// <summary> /// Registers any attributed fields found on the type</summary> /// <param name="type">Type to scan for the attributes Sce.Atf.ImageResourceAttribute and /// Sce.Atf.CursorResourceAttribute, which are usually on static public readonly fields</param> /// <param name="resourcePath">Path to resources in the given type's assembly, deliminated by '.' /// and ending in a '.'</param> public static void Register(Type type, string resourcePath) { Assembly resourceAssembly = type.Assembly; // Register any resources in the assembly foreach (var resName in resourceAssembly.GetManifestResourceNames()) { var ext = Path.GetExtension(resName); if (string.IsNullOrEmpty(ext) || ext.ToLower() != ".png") { continue; } // 16 bit image is the leading image for lookup var fileNameOnly = Path.GetFileNameWithoutExtension(resName); if (!fileNameOnly.EndsWith("_16")) { continue; } var fileNameTemplate = fileNameOnly.Substring(0, fileNameOnly.Length - "_16".Length); string imageName16 = resName; string imageName24 = fileNameTemplate + "_24" + ext; string imageName32 = fileNameTemplate + "_32" + ext; if (resourceAssembly.GetManifestResourceInfo(imageName24) == null) { imageName24 = null; } if (resourceAssembly.GetManifestResourceInfo(imageName32) == null) { imageName32 = null; } RegisterImage(imageName16, GdiUtil.GetImage(resourceAssembly, imageName16), imageName24 != null ? GdiUtil.GetImage(resourceAssembly, imageName24) : null, imageName32 != null ? GdiUtil.GetImage(resourceAssembly, imageName32) : null); } // register fields for custom names FieldInfo[] fields = type.GetFields( BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo field in fields) { object[] attributes; attributes = field.GetCustomAttributes(typeof(ImageResourceAttribute), false); if (attributes.Length > 0) { ImageResourceAttribute attribute = attributes[0] as ImageResourceAttribute; string name1 = resourcePath + attribute.ImageName1; field.SetValue(null, name1); string name2 = attribute.ImageName2 != null ? resourcePath + attribute.ImageName2 : null; string name3 = attribute.ImageName3 != null ? resourcePath + attribute.ImageName3 : null; RegisterImage(resourceAssembly, name1, name2, name3); continue; } attributes = field.GetCustomAttributes(typeof(CursorResourceAttribute), false); if (attributes.Length > 0) { CursorResourceAttribute attribute = attributes[0] as CursorResourceAttribute; string name = resourcePath + attribute.CursorName; field.SetValue(null, name); RegisterCursor(resourceAssembly, name); continue; } } }