namespace AcDream.App.UI; /// /// Retail UIElement_Resizebar (element class 9, /// UIElement_Resizebar::Register @0x0046B920 registers class 9 with the /// LayoutDesc element factory). A leaf grip authored at exactly one edge or /// corner of a window; retail authors 4 edge grips + 4 corner grips per /// resizable window (main chat: 0x1000069B-0x100006A2, minus the /// straight top strip which is a retail UIElement_Dragbar move handle /// instead — see the class doc on /// and docs/research/2026-08-09-chat-retail-window-shell.md §2.1/§2.3). /// /// /// UIElement_Resizebar::StartMouseResizing @0x0046B7E0 reads four BOOL /// attributes off the element — 0x2A=bottom, 0x2B=left, /// 0x2C=right, 0x2D=top — and combines them into a /// BorderLocation (acclient.h:4327). /// is a verbatim port of that branch order. acdream's engine expresses resize /// direction as an edge-flag bitmask () rather than /// retail's nine-case enum; is the lossless projection — /// every value maps to exactly one /// combination and back. /// /// /// /// A grip is a small (5px) leaf with no children and no authored background /// media beyond its own cursor-feedback sprite; it exists purely as a precise /// hit region. gives a directly-hit grip's /// own priority over the generic proximity-based /// heuristic, so e.g. the chat /// window's top-left/top-right CORNER grips resize (including the Y/top axis) /// while the plain top EDGE strip in between remains a pure move handle. /// /// public sealed class UiResizeGrip : UiElement { /// Retail BorderLocation (acclient.h:4327): /// BORDER_NONE=0, BORDER_UL=1, BORDER_TOP=2, BORDER_UR=3, BORDER_RIGHT=4, /// BORDER_LR=5, BORDER_BOTTOM=6, BORDER_LL=7, BORDER_LEFT=8. public enum Border { None = 0, UpperLeft = 1, Top = 2, UpperRight = 3, Right = 4, LowerRight = 5, Bottom = 6, LowerLeft = 7, Left = 8, } /// Decoded retail BorderLocation for this grip. public Border BorderLocation { get; set; } /// /// Exact port of UIElement_Resizebar::StartMouseResizing @0x0046B7E0's /// if/else-if chain (right beats left beats top beats bottom when more than /// two bools are set, which retail's authored data never does — corners set /// exactly two adjacent bools, edges set exactly one). /// public static Border DecodeBorderLocation(bool bottom, bool left, bool right, bool top) { if (right) return top ? Border.UpperRight : bottom ? Border.LowerRight : Border.Right; if (left) return top ? Border.UpperLeft : bottom ? Border.LowerLeft : Border.Left; if (top) return Border.Top; if (bottom) return Border.Bottom; return Border.None; } /// The projection 's resize /// drag state machine consumes — a lossless re-encoding of . public ResizeEdges Edges => BorderLocation switch { Border.UpperLeft => ResizeEdges.Left | ResizeEdges.Top, Border.Top => ResizeEdges.Top, Border.UpperRight => ResizeEdges.Right | ResizeEdges.Top, Border.Right => ResizeEdges.Right, Border.LowerRight => ResizeEdges.Right | ResizeEdges.Bottom, Border.Bottom => ResizeEdges.Bottom, Border.LowerLeft => ResizeEdges.Left | ResizeEdges.Bottom, Border.Left => ResizeEdges.Left, _ => ResizeEdges.None, }; }