/// <summary/> protected override void OnRender(DrawingContext dc) { if (!_needsRendering || ComputedPath == null) return; _needsRendering = false; var P = ComputedPath; var N = P.Count; if (N < 4) return; var g1 = new StreamGeometry(); var c1 = g1.Open(); // draw line c1.BeginFigure(P[0], false, false); for (var i = 1; i < N; i += 3) { c1.BezierTo(P[i], P[i+1], P[i+2], true, false); } c1.Close(); g1.Freeze(); dc.DrawGeometry(null, _lineStroke, g1); // draw arrows var g2 = new StreamGeometry(); var c2 = g2.Open(); var bg = _arrowHollow; if (ComputedArrowHead.HasValue) { var headPoint = ComputedArrowHead.Value; var headVector = _normalize(headPoint - P[N - 1]); if (Role.Has(DiagramEdgeRole.Containment) || Role.Has(DiagramEdgeRole.Association)) { bg = _arrowFilled; _drawFilledArrowHead(c2, headPoint, headVector, 15, 5); } else if (Role.Has(DiagramEdgeRole.WeakAssociation)) { _drawHollowArrowHead(c2, headPoint, headVector, 15, 6); } } if (ComputedArrowTail.HasValue) { var tailPoint = ComputedArrowTail.Value; var tailVector = _normalize(tailPoint - P[0]); if (Role.Has(DiagramEdgeRole.Inheritance)) { _drawTriangularTail(c2, tailPoint, tailVector); } else if (Role.Has(DiagramEdgeRole.Containment)) { _drawCircularTail(c2, tailPoint, tailVector, 5); } } c2.Close(); g2.Freeze(); dc.DrawGeometry(bg, _arrowStroke, g2); // draw label if (Label.NotEmpty()) { var label = DiagramSprite.ToFormattedText(Label, 14, _lineStroke.Brush); var lpos = new Point(LabelPos.X - label.Width / 2 + 15, LabelPos.Y - label.Height / 2); var slope = Math.Atan2(P[N - 1].Y - P[0].Y, P[N - 1].X - P[0].X).ToDegrees(); if (slope > 90 && slope < 270) slope = (slope + 180) % 360; dc.PushRotate(slope, lpos); dc.DrawText(label, lpos); dc.Pop(); } }
/// <summary/> protected override void OnRender(DrawingContext dc) { base.OnRender(dc); if (TickCount <= 0 || !TickThickness.IsPositive()) return; var hasFill = (Fill != null); var hasStroke = (Stroke != null && StrokeThickness > 0); if (!hasFill && !hasStroke) return; double cx, cy, r0, r1; if (!ComputeBoundingCircles(out cx, out cy, out r0, out r1)) return; var geometry = new StreamGeometry(); using (var gc = geometry.Open()) { var d = TickThickness / 2.0; gc.BeginFigure(new Point(cx - d, cy - r0), hasFill, true); gc.LineTo(new Point(cx - d, cy - r1), hasStroke, false); gc.LineTo(new Point(cx + d, cy - r1), hasStroke, false); gc.LineTo(new Point(cx + d, cy - r0), hasStroke, false); } geometry.Freeze(); var a0 = StartAngle; var a1 = EndAngle; Gauge.NormalizeAngularRange(ref a0, ref a1); if (a0.AlmostEquals(a1)) return; var pen = GetStrokePen(); if (TickCount == 1) { dc.PushRotate((a1 + a0) / 2.0, cx, cy); dc.DrawGeometry(Fill, pen, geometry); dc.Pop(); } else { var delta = (a1 - a0) / (TickCount - 1); for (var i = 0; i < TickCount; i++) { if (SkipCount > 0 && (i % SkipCount) == 0) continue; dc.PushRotate(a0 + i * delta, cx, cy); dc.DrawGeometry(Fill, pen, geometry); dc.Pop(); } } }
/// <summary/> protected override void OnRender(DrawingContext dc) { base.OnRender(dc); if (TickCount <= 0 || Foreground == null) return; double cx, cy, r0, r1; if (!ComputeBoundingCircles(out cx, out cy, out r0, out r1)) return; var a0 = StartAngle; var a1 = EndAngle; Gauge.NormalizeAngularRange(ref a0, ref a1); if (a0.AlmostEquals(a1)) return; var typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch); var fontsize = this.IsDefaultValue(FontSizeProperty) ? (r1 - r0) : FontSize; var format = StringFormat.Nvl("{0}"); Action<double, double> drawText = (double n, double a) => { var text = new FormattedText(format.Substitute(n), CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeface, fontsize, Foreground); var tw = text.Width; var th = text.Height; var tb = fontsize - text.Baseline; if (!IsRotated) { var arad = a / 180.0 * Math.PI; dc.PushRotate(-a, cx, cy - r1 + th / 2.0); dc.PushTranslate(-Math.Sin(arad) * tw / 2.0, Math.Cos(arad) * th / 2.0); } dc.DrawText(text, new Point(cx - tw / 2.0, cy - r1 + tb)); if (!IsRotated) { dc.Pop(); dc.Pop(); } }; var pen = GetStrokePen(); if (TickCount == 1) { dc.PushRotate((a1 + a0) / 2.0, cx, cy); drawText((Maximum + Minimum) / 2.0, 0); dc.Pop(); } else { var v0 = Minimum; var v1 = Maximum; Gauge.NormalizeRange(ref v0, ref v1); var angleDelta = (a1 - a0) / (TickCount - 1); var valueDelta = (v1 - v0) / (TickCount - 1); for (var i = 0; i < TickCount; i++) { if (SkipCount > 0 && (i % SkipCount) == 0) continue; dc.PushRotate(a0 + i * angleDelta, cx, cy); drawText(v0 + i * valueDelta, a0 + i * angleDelta); dc.Pop(); } } }
/// <summary/> protected override void OnRender(DrawingContext dc) { base.OnRender(dc); var hasFill = (Fill != null); var hasStroke = (Stroke != null && StrokeThickness > 0); if (!hasFill && !hasStroke) return; double cx, cy, r0, r1; if (!ComputeBoundingCircles(out cx, out cy, out r0, out r1)) return; var d0 = InnerThickness / 2.0; var d1 = OuterThickness / 2.0; if (d0.IsZero() && d1.IsZero()) return; var a = Angle; Gauge.NormalizeAngle(ref a); dc.PushRotate(a, cx, cy); var geometry = new StreamGeometry(); using (var gc = geometry.Open()) { gc.BeginFigure(new Point(cx - d0, cy - r0), hasFill, true); gc.LineTo(new Point(cx - d1, cy - r1), hasStroke, false); gc.LineTo(new Point(cx + d1, cy - r1), hasStroke, false); gc.LineTo(new Point(cx + d0, cy - r0), hasStroke, false); } geometry.Freeze(); dc.DrawGeometry(Fill, GetStrokePen(), geometry); }