aboutsummaryrefslogtreecommitdiffstats
path: root/layout/geo.go
blob: 6f84049b81303ce892701c3c091acfbbe1713de7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package layout

import (
	"fmt"
	"image"
)

// ResizeFunc is a function that computes the area of a layout when it receives a Resize event.
// It takes the Resize's Rectangle and returns the area that the layout should cover.
type ResizeFunc func(image.Rectangle) image.Rectangle

// Full resizes a layout to consume all of its parent's area.
func Full() ResizeFunc {
	return func(r image.Rectangle) image.Rectangle { return r }
}

// Quad1 resizes a layout to consume the top-right quadrant of its parent.
func Quad1() ResizeFunc {
	return func(r image.Rectangle) image.Rectangle {
		mid := midpoint(r)
		return image.Rect(mid.X, r.Min.Y, r.Max.X, mid.Y)
	}
}

// Quad2 resizes a layout to consume the top-left quadrant of its parent.
func Quad2() ResizeFunc {
	return func(r image.Rectangle) image.Rectangle {
		mid := midpoint(r)
		return image.Rectangle{r.Min, mid}
	}
}

// Quad3 resizes a layout to consume the bottom-left quadrant of its parent.
func Quad3() ResizeFunc {
	return func(r image.Rectangle) image.Rectangle {
		mid := midpoint(r)
		return image.Rect(r.Min.X, mid.Y, mid.X, r.Max.Y)
	}
}

// Quad4 resizes a layout to consume the bottom-right quadrant of its parent.
func Quad4() ResizeFunc {
	return func(r image.Rectangle) image.Rectangle {
		mid := midpoint(r)
		return image.Rectangle{mid, r.Max}
	}
}

// Inset resizes a layout to be inset some number of pixels from the edges of its parent.
func Inset(top, right, bottom, left int) ResizeFunc {
	if top < 0 {
		panic(fmt.Sprintf("inset %d < 0", top))
	} else if right < 0 {
		panic(fmt.Sprintf("inset %d < 0", right))
	} else if bottom < 0 {
		panic(fmt.Sprintf("inset %d < 0", bottom))
	} else if left < 0 {
		panic(fmt.Sprintf("inset %d < 0", left))
	}
	return func(r image.Rectangle) image.Rectangle {
		if r.Dx() < left+right {
			r.Min.X = (r.Min.X + r.Max.X) / 2
			r.Max.X = r.Min.X
		} else {
			r.Min.X += left
			r.Max.X -= right
		}
		if r.Dy() < top+bottom {
			r.Min.Y = (r.Min.Y + r.Max.Y) / 2
			r.Max.Y = r.Min.Y
		} else {
			r.Min.Y += top
			r.Max.Y -= bottom
		}
		return r
	}
}

// InsetAll resizes as layout to be inset px pixels on all sides from the edges of its parent.
func InsetAll(px int) ResizeFunc { return Inset(px, px, px, px) }

// InsetTop resizes a layout to be inset px pixels from the top edge of its parent.
func InsetTop(px int) ResizeFunc { return Inset(px, 0, 0, 0) }

// InsetRight resizes a layout to be inset px pixels from the top edge of its parent.
func InsetRight(px int) ResizeFunc { return Inset(0, px, 0, 0) }

// InsetBottom resizes a layout to be inset px pixels from the top edge of its parent.
func InsetBottom(px int) ResizeFunc { return Inset(0, 0, px, 0) }

// InsetLeft resizes a layout to be inset px pixels from the top edge of its parent.
func InsetLeft(px int) ResizeFunc { return Inset(0, 0, 0, px) }

// midpoint returns the point in the middle of a rectangle.
func midpoint(r image.Rectangle) image.Point {
	return r.Min.Add(r.Max).Div(2)
}