1package main 2 3// Rect is a position, width and height 4type Rect struct { 5 X int 6 Y int 7 W int 8 H int 9} 10 11// Box has one outer and one innner rectangle. 12// This is useful when having margins that surrounds content. 13type Box struct { 14 frame *Rect // The rectangle around the box, for placement 15 inner *Rect // The rectangle inside the box, for content 16} 17 18// Create a new Box / container. 19func NewBox() *Box { 20 return &Box{&Rect{0, 0, 0, 0}, &Rect{0, 0, 0, 0}} 21} 22 23// Place a Box at the center of the given container. 24func (b *Box) Center(container *Box) { 25 widthleftover := container.inner.W - b.frame.W 26 heightleftover := container.inner.H - b.frame.H 27 b.frame.X = container.inner.X + widthleftover/2 28 b.frame.Y = container.inner.Y + heightleftover/2 29} 30 31// Place a Box so that it fills the entire given container. 32func (b *Box) Fill(container *Box) { 33 b.frame.X = container.inner.X 34 b.frame.Y = container.inner.Y 35 b.frame.W = container.inner.W 36 b.frame.H = container.inner.H 37} 38 39// Place a Box inside a given container, with the given margins. 40// Margins are given in number of characters. 41func (b *Box) FillWithMargins(container *Box, margins int) { 42 b.Fill(container) 43 b.frame.X += margins 44 b.frame.Y += margins 45 b.frame.W -= margins * 2 46 b.frame.H -= margins * 2 47} 48 49// Place a Box inside a given container, using the given percentage wise ratios. 50// horizmarginp can for example be 0.1 for a 10% horizontal margin around 51// the inner box. vertmarginp works similarly, but for the vertical margins. 52func (b *Box) FillWithPercentageMargins(container *Box, horizmarginp float32, vertmarginp float32) { 53 horizmargin := int(float32(container.inner.W) * horizmarginp) 54 vertmargin := int(float32(container.inner.H) * vertmarginp) 55 b.Fill(container) 56 b.frame.X += horizmargin 57 b.frame.Y += vertmargin 58 b.frame.W -= horizmargin * 2 59 b.frame.H -= vertmargin * 2 60} 61 62// Retrieves the position of the inner rectangle. 63func (b *Box) GetContentPos() (int, int) { 64 return b.inner.X, b.inner.Y 65} 66 67// Set the size of the Box to 1/3 of the size of the inner rectangle 68// of the given container. 69func (b *Box) SetThirdSize(container *Box) { 70 b.frame.W = container.inner.W / 3 71 b.frame.H = container.inner.H / 3 72} 73 74// Set the position of the Box to 1/3 of the size of the inner rectangle 75// of the given container. 76func (b *Box) SetThirdPlace(container *Box) { 77 b.frame.X = container.inner.X + container.inner.W/3 78 b.frame.Y = container.inner.Y + container.inner.H/3 79} 80 81// Place a Box so that it either fills the given 82// container, or is placed 1/3 from the upper left edge, 83// depending on how much space is left. 84func (b *Box) SetNicePlacement(container *Box) { 85 b.frame.X = container.inner.X 86 b.frame.Y = container.inner.Y 87 leftoverwidth := container.inner.W - b.frame.W 88 leftoverheight := container.inner.H - b.frame.H 89 if leftoverwidth > b.frame.W { 90 b.frame.X += leftoverwidth / 3 91 } 92 if leftoverheight > b.frame.H { 93 b.frame.Y += leftoverheight / 3 94 } 95} 96 97// Place a Box within the given container. 98func (b *Box) Place(container *Box) { 99 b.frame.X = container.inner.X 100 b.frame.Y = container.inner.Y 101} 102 103// Place a box at the bottom center of a given container, but a bit to the left 104func (b *Box) BottomCenterLeft(container *Box) { 105 widthleftover := container.inner.W - b.frame.W 106 b.frame.X = container.inner.X + widthleftover/3 107 b.frame.Y = container.inner.Y + container.inner.H - 2 108} 109 110// Place a box at the bottom center of a given container, but a bit to the right 111func (b *Box) BottomCenterRight(container *Box) { 112 widthleftover := container.inner.W - b.frame.W 113 b.frame.X = container.inner.X + container.inner.W - (widthleftover / 2) 114 b.frame.Y = container.inner.Y + container.inner.H - 2 115} 116 117// Get the inner rectangle (content size + pos) 118func (b *Box) GetInner() *Rect { 119 return b.inner 120} 121 122// Get the outer frame (box size + pos) 123func (b *Box) GetFrame() *Rect { 124 return b.frame 125} 126 127// Set the inner rectangle (content size + pos) 128func (b *Box) SetInner(r *Rect) { 129 b.inner = r 130} 131 132// Set the outer frame (box size + pos) 133func (b *Box) SetFrame(r *Rect) { 134 b.frame = r 135} 136