From b37db79a23341a54c7456445ec36bb2116d2453f Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 17 Jun 2026 15:53:53 +0200 Subject: [PATCH] feat(D.5.1): wrap toolbar in UiNineSlicePanel chrome frame (mirrors chat window) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The toolbar LayoutDesc (0x21000016, 300x122) was mounted bare — no window chrome. This commit wraps it in a UiNineSlicePanel (the same 8-piece bevel + gold grip chrome used by the vitals and chat windows), matching the pattern at GameWindow.cs ~line 1885 verbatim. - toolbarFrame is the top-level UiNineSlicePanel (Draggable=true, Anchors=None per UiNineSlicePanel ctor defaults). Outer size = 310x132 (300+2*5 x 122+2*5). - toolbarRoot sits inside at offset (5,5) — the border thickness — with all-edge anchors so it reflows if the frame is resized. Draggable=false, Resizable=false on the content (only the frame is the drag handle). - The frame's right border (x=305..310 screen) covers the row-2 right cap overhang (~2px past the content edge at x=300..302), since the border region starts at content_right=300 and extends to frame_right=310. - Probe block untouched: still calls toolbarLayout.FindElement for diagnostic ids. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/AcDream.App/Rendering/GameWindow.cs | 35 +++++++++++++++++++------ 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index ea4d06ac..e05ecc23 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -2010,15 +2010,34 @@ public sealed class GameWindow : IDisposable emptyDigits: toolbarEmptyDigits); var toolbarRoot = toolbarLayout.Root; - toolbarRoot.Left = 10; toolbarRoot.Top = 300; - // D1: Anchors=None so ApplyAnchor skips re-pinning every frame and - // the drag position is preserved (matches vitalsRoot pattern). - toolbarRoot.Anchors = AcDream.App.UI.AnchorEdges.None; - // D2: UiDatElement ctor defaults ClickThrough=true; override so the - // chrome is hittable and the drag can start (matches vitalsRoot pattern). + // Wrap the dat content in the universal 8-piece beveled window chrome — + // the SAME UiNineSlicePanel used by the vitals and chat windows. The + // toolbar LayoutDesc (0x21000016) is 300×122; the frame adds one border + // thickness on every side, giving an outer window of 310×132. + const int toolbarBorder = AcDream.App.UI.RetailChromeSprites.Border; + float toolbarContentW = 300f, toolbarContentH = toolbarRoot.Height; + var toolbarFrame = new AcDream.App.UI.UiNineSlicePanel(ResolveChrome) + { + Left = 10, Top = 300, + Width = toolbarContentW + 2 * toolbarBorder, + Height = toolbarContentH + 2 * toolbarBorder, + // The toolbar is fully opaque (not translucent like the chat window). + Opacity = 1.0f, + }; + // Content is offset by the border so it sits inside the chrome. + toolbarRoot.Left = toolbarBorder; + toolbarRoot.Top = toolbarBorder; + toolbarRoot.Width = toolbarContentW; + toolbarRoot.Height = toolbarContentH; + // Anchor content to all four edges so it reflows if the frame is resized. + toolbarRoot.Anchors = AcDream.App.UI.AnchorEdges.Left | AcDream.App.UI.AnchorEdges.Top + | AcDream.App.UI.AnchorEdges.Right | AcDream.App.UI.AnchorEdges.Bottom; + // The frame is the draggable window; the content itself is not. toolbarRoot.ClickThrough = false; - toolbarRoot.Draggable = true; - _uiHost.Root.AddChild(toolbarRoot); + toolbarRoot.Draggable = false; + toolbarRoot.Resizable = false; + toolbarFrame.AddChild(toolbarRoot); + _uiHost.Root.AddChild(toolbarFrame); // [D.5.1 PROBE] Bottom-right geometry rect dump — temporary diagnostic. // Localises the bottom-right mismatch reported by the user; remove once fixed.