1package ui
2
3import "github.com/bnema/vev/internal/domain"
4
5// Margins specifies the distance between an anchored rectangle and each base edge.
6type Margins struct {
7 Top, Right, Bottom, Left int
8}
9
10// Place positions content in base according to anchor. Negative margins and
11// content dimensions are normalized to zero. The returned rectangle is always
12// contained within a positive base; a nonpositive base returns an empty rect.
13func Place(base, content domain.Size, anchor domain.Anchor, margins Margins) domain.Rect {
14 if !base.Valid() {
15 return domain.Rect{}
16 }
17
18 width := clamp(content.Cols, 0, base.Cols)
19 height := clamp(content.Rows, 0, base.Rows)
20 margins.Top = max(0, margins.Top)
21 margins.Right = max(0, margins.Right)
22 margins.Bottom = max(0, margins.Bottom)
23 margins.Left = max(0, margins.Left)
24
25 x := (base.Cols - width) / 2
26 y := (base.Rows - height) / 2
27 switch anchor {
28 case domain.AnchorTopLeft:
29 x, y = margins.Left, margins.Top
30 case domain.AnchorTop:
31 y = margins.Top
32 case domain.AnchorTopRight:
33 x, y = base.Cols-margins.Right-width, margins.Top
34 case domain.AnchorLeft:
35 x = margins.Left
36 case domain.AnchorRight:
37 x = base.Cols - margins.Right - width
38 case domain.AnchorBottomLeft:
39 x, y = margins.Left, base.Rows-margins.Bottom-height
40 case domain.AnchorBottom:
41 y = base.Rows - margins.Bottom - height
42 case domain.AnchorBottomRight:
43 x, y = base.Cols-margins.Right-width, base.Rows-margins.Bottom-height
44 case domain.AnchorCenter:
45 // Center is the zero value and intentionally ignores all margins.
46 default:
47 // Invalid anchors fall back to center.
48 }
49
50 return domain.Rect{
51 X: clamp(x, 0, base.Cols-width),
52 Y: clamp(y, 0, base.Rows-height),
53 Width: width,
54 Height: height,
55 }
56}
57
58func clamp(n, low, high int) int {
59 if n < low {
60 return low
61 }
62 if n > high {
63 return high
64 }
65 return n
66}