Forge
csharpdeeb25a2
1#nullable enable
2
3namespace CascadeIDE.Views.SkiaKit;
4
5/// <summary>Раскладка плиток в сетке для Skia-surfaces (картотека тем, graph cards, …).</summary>
6internal readonly record struct SkiaTileGridOptions(
7 float MinTileWidth = 200f,
8 float GapX = 12f,
9 float GapY = 12f,
10 float OriginX = 12f,
11 int MaxColumns = 4);
12
13internal readonly record struct SkiaTilePlacement(float Left, float Top, float Width);
14
15internal static class SkiaTileGridLayout
16{
17 public static int ComputeColumnCount(float contentWidth, in SkiaTileGridOptions options)
18 {
19 if (contentWidth <= options.MinTileWidth)
20 return 1;
21 var columns = (int)((contentWidth + options.GapX) / (options.MinTileWidth + options.GapX));
22 return Math.Clamp(columns, 1, options.MaxColumns);
23 }
24
25 public static float TileWidth(float contentWidth, int columns, in SkiaTileGridOptions options) =>
26 (contentWidth - options.GapX * (columns - 1)) / columns;
27
28 /// <summary>
29 /// Раскладывает элементы в сетку; <paramref name="measureHeight"/> вызывается с шириной плитки.
30 /// Возвращает новую Y после блока и список размещений (порядок совпадает с <paramref name="items"/>).
31 /// </summary>
32 public static (float NextY, IReadOnlyList<SkiaTilePlacement> Placements) Layout<T>(
33 IReadOnlyList<T> items,
34 float contentWidth,
35 float startY,
36 in SkiaTileGridOptions options,
37 Func<T, float, float> measureHeight)
38 {
39 if (items.Count == 0)
40 return (startY, Array.Empty<SkiaTilePlacement>());
41
42 var columns = ComputeColumnCount(contentWidth, in options);
43 var tileWidth = TileWidth(contentWidth, columns, in options);
44 var placements = new SkiaTilePlacement[items.Count];
45 var col = 0;
46 var rowStartY = startY;
47 var rowMaxHeight = 0f;
48
49 for (var i = 0; i < items.Count; i++)
50 {
51 var height = measureHeight(items[i], tileWidth);
52 var left = options.OriginX + col * (tileWidth + options.GapX);
53 placements[i] = new SkiaTilePlacement(left, rowStartY, tileWidth);
54 rowMaxHeight = Math.Max(rowMaxHeight, height);
55 col++;
56 if (col < columns)
57 continue;
58
59 col = 0;
60 rowStartY += rowMaxHeight + options.GapY;
61 rowMaxHeight = 0f;
62 }
63
64 if (col > 0)
65 rowStartY += rowMaxHeight;
66
67 return (rowStartY + options.GapY, placements);
68 }
69}
70
View only · write via MCP/CIDE