Forge
csharpdeeb25a2
1#nullable enable
2using Avalonia;
3using Avalonia.Media;
4using CascadeIDE.Cockpit.Graph.Layout;
5
6namespace CascadeIDE.Views.SkiaKit.Graph;
7
8public static partial class SkiaGraphSceneDrawing
9{
10 /// <summary>Овал вокруг узлов одного <see cref="GraphLayoutNode.LoopGroupId"/> (цикл while/for/foreach/do).</summary>
11 private static void DrawLoopGroupOutlines(DrawingContext context, GraphLayoutScene scene, SkiaGraphVisualTheme theme)
12 {
13 if (scene.Presentation != GraphLayoutPresentation.CodeControlFlow || scene.Nodes.Count == 0)
14 return;
15
16 if (theme.LoopEdgePen.Brush is not SolidColorBrush scb)
17 return;
18
19 var loopColor = scb.Color;
20 var stroke = new SolidColorBrush(
21 Color.FromArgb((byte)Math.Clamp((int)(loopColor.A * 0.28), 16, 72), loopColor.R, loopColor.G, loopColor.B));
22 var dashPen = new Pen(stroke, 1.0) { DashStyle = new DashStyle([6, 5], 0) };
23
24 foreach (var g in scene.Nodes
25 .Where(n => n.LoopGroupId > 0)
26 .GroupBy(n => n.LoopGroupId!.Value))
27 {
28 var nodes = g.ToList();
29 if (nodes.Count < 2)
30 continue;
31
32 var minX = double.PositiveInfinity;
33 var minY = double.PositiveInfinity;
34 var maxX = double.NegativeInfinity;
35 var maxY = double.NegativeInfinity;
36 foreach (var n in nodes)
37 {
38 var rEff = n.Shape == GraphNodeShape.Condition ? n.Radius * 1.08 : n.Radius;
39 minX = Math.Min(minX, n.Center.X - rEff);
40 maxX = Math.Max(maxX, n.Center.X + rEff);
41 minY = Math.Min(minY, n.Center.Y - rEff);
42 maxY = Math.Max(maxY, n.Center.Y + rEff);
43 }
44
45 const double pad = 14;
46 var cx = (minX + maxX) * 0.5;
47 var cy = (minY + maxY) * 0.5;
48 var rx = (maxX - minX) * 0.5 + pad;
49 var ry = (maxY - minY) * 0.5 + pad;
50 if (rx < 6 || ry < 6)
51 continue;
52
53 context.DrawEllipse(null, dashPen, new Point(cx, cy), rx, ry);
54 }
55 }
56}
57
View only · write via MCP/CIDE