private void PaintElement(GraphicsProxy g, Elem e) { Node node = e.GetNode(); Point placement = e.Location; bool isSelected = m_selected.Contains(e); if (e.Parent != null) g.DrawLine(StandardLinePen(), placement.X + e.Dimensions.Width / 2, placement.Y, e.Parent.Location.X + e.Parent.Dimensions.Width / 2, e.Parent.Location.Y + e.Parent.Dimensions.Height); if (node.IsBlank()) { if (isSelected) g.FillRectangle(HighlightBackBrush(), placement.X, placement.Y, e.Dimensions.Width - 1, e.Dimensions.Height - 1); /*the minus 1 in the above line prevent a weird screen artefact when drawing the selected variant of the red X when antialiasing is on. It looks like the antialiasing actually draws pixels outside the box specified? One solution would be to push antialias state, turn it off, draw the box, and pop antialias state, but this is faster and adequate*/ DrawBigX(g, placement.X + (e.Dimensions.Width / 2), placement.Y + (e.Dimensions.Height / 2)); } else { Graphics realGraphics = g.Graphics; if (realGraphics == null) RenderNode(g, e, e.Rect, isSelected, false); else { if (e.cache == null) { Bitmap bm = new Bitmap(e.Dimensions.Width, e.Dimensions.Height); using (Graphics bmGraphics = Graphics.FromImage(bm)) { GraphicsPassThrough gp = new GraphicsPassThrough(bmGraphics); SetupAntiAliasing(gp); RenderNodePositionInfo rnpi = RenderNode(gp, e, new Rectangle(Point.Empty, e.Dimensions), false, true); e.labelRect = rnpi.labelRect; e.lexRect = rnpi.lexRect; } e.cache = bm; bm = new Bitmap(e.Dimensions.Width, e.Dimensions.Height); using (Graphics bmGraphics = Graphics.FromImage(bm)) { GraphicsPassThrough gp = new GraphicsPassThrough(bmGraphics); SetupAntiAliasing(gp); RenderNode(gp, e, new Rectangle(Point.Empty, e.Dimensions), true, false); } e.cacheSelected = bm; } realGraphics.DrawImageUnscaled(isSelected ? e.cacheSelected : e.cache, e.Location); /* * I would like to draw the image with transparency, but this * produces problems since the text image includes gradients * resulting from text antialiasing System.Drawing.Imaging.ImageAttributes attrs= new System.Drawing.Imaging.ImageAttributes(); attrs.SetColorKey(Color.White, Color.White); realGraphics.DrawImage(isSelected ? e.cacheSelected : e.cache, e.Rect, 0, 0, e.Rect.Width, e.Rect.Height, GraphicsUnit.Pixel, attrs); */ } if (node.GetDisplayType() == NodeDisplayType.Triangle) { int paddingvertical = PaddingVertical(); Rectangle lexRect = e.lexRect; Rectangle labelRect = e.labelRect; lexRect.Offset(e.Location); labelRect.Offset(e.Location); g.DrawPolygon(StandardLinePen(), new Point[] { new Point(lexRect.Left,lexRect.Top-paddingvertical), new Point(lexRect.Right,lexRect.Top-paddingvertical), new Point(labelRect.Left+labelRect.Width/2,labelRect.Bottom+paddingvertical) }); } } Decoration decoration = node.Decoration; if (decoration.mode != DecorationMode.None) { int pv = PaddingVertical() / 2 + (int)node.Decoration.penstyle.width; int ph = PaddingHorizontal() / 2 + (int)node.Decoration.penstyle.width; int pd = node.Decoration.padding; Rectangle decorationRect; if (decoration.mode == DecorationMode.Node) decorationRect = new Rectangle(e.Rect.Left + ph, e.Rect.Top + pv, e.Rect.Width - ph * 2, e.Rect.Height - pv * 2); else { // subtree mode decorationRect = OptGetSubTreeRectangle(e); decorationRect.Inflate(pd, pd); } switch (decoration.shape) { case DecorationShape.Ellipse: using (Pen pen = decoration.penstyle.GetPen(GetZoomFactor())) g.DrawEllipse(pen, decorationRect.Left, decorationRect.Top, decorationRect.Width, decorationRect.Height); break; case DecorationShape.Cross: using (Pen pen = decoration.penstyle.GetPen(GetZoomFactor())) { g.DrawLine(pen, decorationRect.Left, decorationRect.Top, decorationRect.Left + decorationRect.Width, decorationRect.Height + decorationRect.Top); g.DrawLine(pen, decorationRect.Left, decorationRect.Top + decorationRect.Height, decorationRect.Left + decorationRect.Width, decorationRect.Top); } break; case DecorationShape.Rectangle: using (Pen pen = decoration.penstyle.GetPen(GetZoomFactor())) g.DrawRectangle(pen, decorationRect.Left, decorationRect.Top, decorationRect.Width, decorationRect.Height); break; default: throw new Exception("unknown shape"); } } /*in determining how to vertically space traces, we should perhaps use a fancier algorithm, so that their height is offset only if they would actually cross. An reasonable approximation of such a fancy algorithm might keep track of traceCount on a per-level basis, rather than a per-common-ancestor basis * This block, which draws the traces, shouldn't be here, * as traces shouldn't be members of elements */ int traceCount = 0; foreach (ElemTrace elemtrace in e.Traces()) { traceCount++; using (Pen pen = elemtrace.trace.penstyle.GetPen(GetZoomFactor())) { Point[] points = elemtrace.GetPoints(e, TraceSpacingHorizontal(), TraceSpacingVertical(), traceCount); switch (elemtrace.trace.tracestyle) { case TraceStyle.Line: g.DrawLines(pen, points); break; case TraceStyle.Curve: g.DrawBezier(pen, points[0], points[1], points[points.Length - 2], points[points.Length - 1]); break; default: throw new TreeException("Unknown trace style"); } } } }
void ExtendMaximumExtents(Elem elem) { Decoration dec = elem.GetNode().Decoration; if (dec.mode == DecorationMode.Subtree) { Rectangle decorationRect = OptGetSubTreeRectangle(elem); decorationRect.Inflate(dec.padding + (int)dec.penstyle.width, dec.padding + (int)dec.penstyle.width); m_maximumExtents = Rectangle.Union(m_maximumExtents, decorationRect); } foreach (ElemTrace elemtrace in elem.Traces()) { Rectangle r = elemtrace.GetRectangle(elem, TraceSpacingHorizontal(), TraceSpacingVertical(), elem.NumTraces()); r.Inflate((int)elemtrace.trace.penstyle.width, (int)elemtrace.trace.penstyle.width); m_maximumExtents = Rectangle.Union(m_maximumExtents, r); } }