pub fn anchored_rect(
anchor: Rect,
size: Size,
preferred: Side,
bounds: Rect,
) -> RectExpand description
Place a size panel adjacent to anchor, preferring side, flipping to the opposite side
when there isn’t room, and clamped to stay within bounds.
side decides which edge of anchor the panel opens from: Side::Below/Side::Above
place the panel’s left edge at anchor’s left edge and stack it vertically off anchor’s
bottom/top edge; Side::Right/Side::Left place the panel’s top edge at anchor’s top
edge and lay it out horizontally off anchor‘s right/left edge. If the preferred side doesn’t
have enough room within bounds (the panel’s far edge would fall outside bounds on that
axis) but the opposite side does, the panel opens on the opposite side instead; if neither
side has room, the preferred side is kept and clamped like the fitting case. Once a side is
chosen, the panel is clamped along the perpendicular axis so it never runs past bounds’
edges: this is the three-line clamp a hand-rolled dropdown would otherwise repeat
(x.min(bounds.right() - width).max(bounds.left())), applied to whichever axis side didn’t
already pin.
size is clamped down to bounds’ own dimensions if larger, so the result is always fully
within bounds, the same guarantee centered_rect makes for a centered box.
Pure layout math: no drawing, no Terminal. Callers still own sizing (deciding size from
content, with a floor/ceiling) and overflow (scrolling when content is taller than the
resulting rect); this only answers where the rect goes.
Never panics: every offset is computed with saturating arithmetic, so a degenerate anchor,
size, or bounds (zero width/height, or anchor outside bounds) resolves to a clamped,
zero-size-or-larger rect instead of under/overflowing.
§Examples
use retroglyph_core::grid::{Rect, Size};
use retroglyph_ui::{Side, anchored_rect};
let bounds = Rect::new(0, 0, 40, 20);
let anchor = Rect::new(5, 5, 10, 1); // e.g. a menu label
let rect = anchored_rect(anchor, Size::new(12, 4), Side::Below, bounds);
assert_eq!(rect, Rect::new(5, 6, 12, 4));