Forge
csharpdeeb25a2
1using SkiaSharp;
2
3namespace CascadeIDE.Views.Chat.Skia;
4
5/// <summary>Колонка роли слева от тела сообщения — метрики из <see cref="SkiaChatFeedLayout"/>.</summary>
6internal static class SkiaChatFeedRoleRail
7{
8 public static void Draw(
9 SKCanvas canvas,
10 SkiaChatTheme theme,
11 float railLeft,
12 float top,
13 float bottom,
14 string roleLabel,
15 in SkiaChatFeedLayout layout)
16 {
17 if (string.IsNullOrWhiteSpace(roleLabel))
18 return;
19
20 var railWidth = layout.RoleRailWidth;
21 var railRect = new SKRect(railLeft, top, railLeft + railWidth, bottom);
22 canvas.Save();
23 canvas.ClipRect(railRect);
24
25 using var rulePaint = new SKPaint
26 {
27 Color = theme.Border.WithAlpha(90),
28 IsAntialias = true,
29 Style = SKPaintStyle.Stroke,
30 StrokeWidth = 1f,
31 };
32 canvas.DrawLine(railRect.Right, railRect.Top + layout.RowEdgePad, railRect.Right, railRect.Bottom - layout.RowEdgePad, rulePaint);
33
34 using var font = SkiaChatFeedFontResolver.CreateFont(
35 layout.RoleFamily,
36 layout.RoleLabelFontSize,
37 SKFontStyle.Bold);
38 using var paint = new SKPaint
39 {
40 IsAntialias = true,
41 Color = theme.Role.WithAlpha(235),
42 };
43 var baseline = layout.RoleLabelBaselineY(top);
44 var text = TruncateToWidth(roleLabel, font, layout.RoleLabelMaxWidth);
45 canvas.DrawText(text, railLeft + layout.RoleLabelInset, baseline, SKTextAlign.Left, font, paint);
46 canvas.Restore();
47 }
48
49 private static string TruncateToWidth(string text, SKFont font, float maxWidth)
50 {
51 if (string.IsNullOrEmpty(text) || font.MeasureText(text) <= maxWidth)
52 return text;
53
54 const string ellipsis = "…";
55 var ellipsisWidth = font.MeasureText(ellipsis);
56 var maxBody = Math.Max(0f, maxWidth - ellipsisWidth);
57 for (var len = text.Length; len > 0; len--)
58 {
59 var slice = text[..len];
60 if (font.MeasureText(slice) <= maxBody)
61 return slice + ellipsis;
62 }
63
64 return ellipsis;
65 }
66}
67
View only · write via MCP/CIDE