Forge
csharpdeeb25a2
1using System.Text.Json;
2using Avalonia;
3using Avalonia.Controls;
4using Avalonia.Layout;
5using Avalonia.VisualTree;
6
7namespace CascadeIDE.Services;
8
9/// <summary>
10/// Применить к контролу параметры layout на лету (margin, grid row/column, canvas left/top, dock).
11/// Вызывать из UI-потока. Для ide_set_control_layout.
12/// </summary>
13public static class UiControlLayoutApply
14{
15 /// <summary>Применить layout из JSON. Возвращает "OK" или сообщение об ошибке.</summary>
16 /// <param name="root">Корень дерева (обычно окно).</param>
17 /// <param name="controlName">Имя контрола (из ide_get_ui_layout).</param>
18 /// <param name="layoutJson">JSON: margin, grid_row, grid_column, grid_row_span, grid_column_span, canvas_left, canvas_top, dock, visible (true/false — скрыть/показать).</param>
19 public static string Apply(Visual root, string controlName, string layoutJson)
20 {
21 if (string.IsNullOrWhiteSpace(controlName))
22 return "Missing control name.";
23
24 var control = root is Window mw
25 ? UiControlAppearance.FindControlByNameAcrossAllWindows(mw, controlName.Trim())
26 : UiControlAppearance.FindControlByName(root, controlName.Trim());
27 if (control is null)
28 return $"Control not found: {controlName}.";
29
30 try
31 {
32 using var doc = JsonDocument.Parse(layoutJson);
33 var rootEl = doc.RootElement;
34
35 if (rootEl.TryGetProperty("margin", out var marginEl))
36 {
37 var t = ParseThickness(marginEl);
38 if (t is { } thickness)
39 control.Margin = thickness;
40 }
41
42 if (rootEl.TryGetProperty("grid_row", out var rowEl) && rowEl.TryGetInt32(out var row))
43 Grid.SetRow(control, row);
44 if (rootEl.TryGetProperty("grid_column", out var colEl) && colEl.TryGetInt32(out var col))
45 Grid.SetColumn(control, col);
46 if (rootEl.TryGetProperty("grid_row_span", out var rowSpanEl) && rowSpanEl.TryGetInt32(out var rowSpan))
47 Grid.SetRowSpan(control, rowSpan);
48 if (rootEl.TryGetProperty("grid_column_span", out var colSpanEl) && colSpanEl.TryGetInt32(out var colSpan))
49 Grid.SetColumnSpan(control, colSpan);
50
51 if (rootEl.TryGetProperty("canvas_left", out var leftEl) && leftEl.TryGetDouble(out var canvasLeft))
52 Canvas.SetLeft(control, canvasLeft);
53 if (rootEl.TryGetProperty("canvas_top", out var topEl) && topEl.TryGetDouble(out var canvasTop))
54 Canvas.SetTop(control, canvasTop);
55
56 if (rootEl.TryGetProperty("dock", out var dockEl))
57 {
58 var dockStr = dockEl.GetString()?.Trim();
59 if (Enum.TryParse<Avalonia.Controls.Dock>(dockStr, ignoreCase: true, out var dock))
60 DockPanel.SetDock(control, dock);
61 }
62
63 if (rootEl.TryGetProperty("visible", out var visEl) && (visEl.ValueKind == JsonValueKind.True || visEl.ValueKind == JsonValueKind.False))
64 control.IsVisible = visEl.GetBoolean();
65
66 return "OK";
67 }
68 catch (JsonException ex)
69 {
70 return "Invalid layout JSON: " + ex.Message;
71 }
72 }
73
74 private static Thickness? ParseThickness(JsonElement el)
75 {
76 if (el.ValueKind == JsonValueKind.Array && el.GetArrayLength() >= 4)
77 {
78 var a = el;
79 return new Thickness(a[0].GetDouble(), a[1].GetDouble(), a[2].GetDouble(), a[3].GetDouble());
80 }
81 if (el.ValueKind == JsonValueKind.Object)
82 {
83 var left = el.TryGetProperty("left", out var l) ? l.GetDouble() : 0;
84 var top = el.TryGetProperty("top", out var t) ? t.GetDouble() : 0;
85 var right = el.TryGetProperty("right", out var r) ? r.GetDouble() : 0;
86 var bottom = el.TryGetProperty("bottom", out var b) ? b.GetDouble() : 0;
87 return new Thickness(left, top, right, bottom);
88 }
89 return null;
90 }
91}
92
View only · write via MCP/CIDE