Forge
csharpdeeb25a2
1#nullable enable
2using CascadeIDE.Features.Chat;
3using CascadeIDE.Views.SkiaKit;
4using SkiaSharp;
5
6namespace CascadeIDE.Views.Chat.Skia;
7
8/// <summary>Интерактивный список/дерево тем после <c>/topic list|tree</c>.</summary>
9internal sealed class SkiaChatTopicPickerEntity(
10 TopicPickerPresentation mode,
11 IReadOnlyList<ChatThreadNode> threads,
12 IReadOnlyDictionary<Guid, int> messageCounts) : ISkiaChatEntity
13{
14 private const float Padding = 10f;
15 private const float RowHeight = 34f;
16 private const float RowGap = 4f;
17 private const float IndentPerDepth = 14f;
18
19 private readonly IReadOnlyList<ChatThreadPresentation.PickerRow> _rows =
20 ChatThreadPresentation.BuildPickerRows(mode, threads, messageCounts);
21
22 public SkiaChatMeasuredLayout Measure(SkiaChatMeasureContext context)
23 {
24 if (_rows.Count == 0)
25 return new SkiaChatMeasuredLayout(40f, 8f);
26
27 var height = Padding + 20f + _rows.Count * RowHeight + (_rows.Count - 1) * RowGap + Padding;
28 return new SkiaChatMeasuredLayout(height, 10f);
29 }
30
31 public void Draw(SkiaChatDrawContext context, float top, in SkiaChatMeasuredLayout layout)
32 {
33 var rect = new SKRect(context.ContentLeft, top, context.ContentLeft + context.ContentWidth, top + layout.Height);
34 using var panelFill = new SKPaint
35 {
36 Color = SkiaKitColor.Blend(context.Theme.Surface, context.Theme.Border, 0.12f),
37 IsAntialias = true,
38 };
39 context.Canvas.DrawRoundRect(rect, 8, 8, panelFill);
40
41 using var headerFont = new SKFont(SKTypeface.FromFamilyName("Segoe UI", SKFontStyle.Bold), 12f);
42 using var headerPaint = new SKPaint { IsAntialias = true, Color = context.Theme.MutedContent };
43 var header = mode == TopicPickerPresentation.Tree
44 ? "Дерево тем — клик для открытия"
45 : "Список тем — клик для открытия";
46 context.Canvas.DrawText(header, rect.Left + Padding, rect.Top + Padding + 12f, SKTextAlign.Left, headerFont, headerPaint);
47
48 var y = rect.Top + Padding + 20f;
49 foreach (var row in _rows)
50 {
51 var rowRect = new SKRect(rect.Left + Padding, y, rect.Right - Padding, y + RowHeight);
52 using var rowFill = new SKPaint
53 {
54 Color = SkiaKitColor.Blend(context.Theme.Surface, context.Theme.Border, 0.2f),
55 IsAntialias = true,
56 };
57 context.Canvas.DrawRoundRect(rowRect, 6, 6, rowFill);
58
59 using var titleFont = new SKFont(SKTypeface.FromFamilyName("Segoe UI", SKFontStyle.Normal), 12.5f);
60 using var titlePaint = new SKPaint { IsAntialias = true, Color = context.Theme.Content };
61 var titleX = rowRect.Left + 8f + row.Depth * IndentPerDepth;
62 context.Canvas.DrawText(row.Title, titleX, rowRect.MidY + 4f, SKTextAlign.Left, titleFont, titlePaint);
63
64 using var metaFont = new SKFont(SKTypeface.FromFamilyName("Segoe UI", SKFontStyle.Normal), 10.5f);
65 using var metaPaint = new SKPaint { IsAntialias = true, Color = context.Theme.MutedContent };
66 context.Canvas.DrawText(row.Meta, rowRect.Right - 8f, rowRect.MidY + 4f, SKTextAlign.Right, metaFont, metaPaint);
67
68 context.RegisterHit(rowRect, new SkiaChatHit(null, row.ThreadId, ResetDetailMode: false));
69 y += RowHeight + RowGap;
70 }
71 }
72
73 public SkiaChatHit? CreateHit(in SkiaChatMeasuredLayout layout) => null;
74}
75
View only · write via MCP/CIDE