about summary refs log tree commit diff stats
path: root/lib/ui/popover.go
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ui/popover.go')
-rw-r--r--lib/ui/popover.go62
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/ui/popover.go b/lib/ui/popover.go
new file mode 100644
index 0000000..a76f222
--- /dev/null
+++ b/lib/ui/popover.go
@@ -0,0 +1,62 @@
+package ui
+
+import "github.com/gdamore/tcell"
+
+type Popover struct {
+	x, y, width, height int
+	content             Drawable
+}
+
+func (p *Popover) Draw(ctx *Context) {
+	var subcontext *Context
+
+	// trim desired width to fit
+	width := p.width
+	if p.x+p.width > ctx.Width() {
+		width = ctx.Width() - p.x
+	}
+
+	if p.y+p.height+1 < ctx.Height() {
+		// draw below
+		subcontext = ctx.Subcontext(p.x, p.y+1, width, p.height)
+	} else if p.y-p.height >= 0 {
+		// draw above
+		subcontext = ctx.Subcontext(p.x, p.y-p.height, width, p.height)
+	} else {
+		// can't fit entirely above or below, so find the largest available
+		// vertical space and shrink to fit
+		if p.y > ctx.Height()-p.y {
+			// there is more space above than below
+			height := p.y
+			subcontext = ctx.Subcontext(p.x, 0, width, height)
+		} else {
+			// there is more space below than above
+			height := ctx.Height() - p.y
+			subcontext = ctx.Subcontext(p.x, p.y+1, width, height-1)
+		}
+	}
+	p.content.Draw(subcontext)
+}
+
+func (p *Popover) Event(e tcell.Event) bool {
+	if di, ok := p.content.(DrawableInteractive); ok {
+		return di.Event(e)
+	}
+	return false
+}
+
+func (p *Popover) Focus(f bool) {
+	if di, ok := p.content.(DrawableInteractive); ok {
+		di.Focus(f)
+	}
+}
+
+func (p *Popover) Invalidate() {
+	p.content.Invalidate()
+}
+
+func (p *Popover) OnInvalidate(f func(Drawable)) {
+	p.content.OnInvalidate(func(_ Drawable) {
+		f(p)
+	})
+}