termbox-util/termbox_util.go

222 lines
5.9 KiB
Go

package termboxUtil
import (
"errors"
"fmt"
"strings"
"github.com/nsf/termbox-go"
)
type termboxControl interface {
GetID() string
GetX() int
SetX(int)
GetY() int
SetY(int)
GetWidth() int
SetWidth(int)
GetHeight() int
SetHeight(int)
GetFgColor() termbox.Attribute
SetFgColor(termbox.Attribute)
GetBgColor() termbox.Attribute
SetBgColor(termbox.Attribute)
HandleEvent(termbox.Event) bool
IsBordered() bool
SetBordered(bool)
SetTabSkip(bool)
IsTabSkipped() bool
Draw()
SetActive(bool)
IsActive() bool
SetActiveFgColor(termbox.Attribute)
SetActiveBgColor(termbox.Attribute)
}
// TextAlignment is an int value for how we're aligning text
type TextAlignment int
const (
// AlignLeft Aligns text to the left
AlignLeft = iota
// AlignCenter Aligns text to the center
AlignCenter
// AlignRight Aligns text to the right
AlignRight
)
/* Basic Input Helpers */
// KeyIsAlphaNumeric Returns whether the termbox event is an
// Alpha-Numeric Key Press
func KeyIsAlphaNumeric(event termbox.Event) bool {
return KeyIsAlpha(event) || KeyIsNumeric(event)
}
// KeyIsAlpha Returns whether the termbox event is a
// alphabetic Key press
func KeyIsAlpha(event termbox.Event) bool {
k := event.Ch
if (k >= 'a' && k <= 'z') || (k >= 'A' && k <= 'Z') {
return true
}
return false
}
// KeyIsNumeric Returns whether the termbox event is a
// numeric Key press
func KeyIsNumeric(event termbox.Event) bool {
k := event.Ch
if k >= '0' && k <= '9' {
return true
}
return false
}
// KeyIsSymbol Returns whether the termbox event is a
// symbol Key press
func KeyIsSymbol(event termbox.Event) bool {
symbols := []rune{'!', '@', '#', '$', '%', '^', '&', '*',
'(', ')', '-', '_', '=', '+', '[', ']', '{', '}', '|',
';', ':', '"', '\'', ',', '<', '.', '>', '/', '?', '`', '~'}
k := event.Ch
for i := range symbols {
if k == symbols[i] {
return true
}
}
return false
}
/* Basic Output Helpers */
// DrawStringAtPoint Draw a string of text at x, y with foreground color fg, background color bg
func DrawStringAtPoint(str string, x int, y int, fg termbox.Attribute, bg termbox.Attribute) (int, int) {
xPos := x
for _, runeValue := range str {
termbox.SetCell(xPos, y, runeValue, fg, bg)
xPos++
}
return xPos, y
}
// FillWithChar Fills from x1,y1 through x2,y2 with the rune r, foreground color fg, background bg
func FillWithChar(r rune, x1, y1, x2, y2 int, fg termbox.Attribute, bg termbox.Attribute) {
for xx := x1; xx <= x2; xx++ {
for yx := y1; yx <= y2; yx++ {
termbox.SetCell(xx, yx, r, fg, bg)
}
}
}
// DrawBorder Draw a border around the area inside x1,y1 -> x2, y2
func DrawBorder(x1, y1, x2, y2 int, fg, bg termbox.Attribute) {
termbox.SetCell(x1, y1, '╔', fg, bg)
FillWithChar('═', x1+1, y1, x2-1, y1, fg, bg)
termbox.SetCell(x2, y1, '╗', fg, bg)
FillWithChar('║', x1, y1+1, x1, y2-1, fg, bg)
FillWithChar('║', x2, y1+1, x2, y2-1, fg, bg)
termbox.SetCell(x1, y2, '╚', fg, bg)
FillWithChar('═', x1+1, y2, x2-1, y2, fg, bg)
termbox.SetCell(x2, y2, '╝', fg, bg)
}
func DrawBorderWithPct(x1, y1, x2, y2 int, pct float64, fg, bg termbox.Attribute) {
termbox.SetCell(x1, y1, '╔', fg, bg)
FillWithChar('═', x1+1, y1, x2-1, y1, fg, bg)
termbox.SetCell(x2, y1, '╗', fg, bg)
FillWithChar('║', x1, y1+1, x1, y2-1, fg, bg)
FillWithChar('║', x2, y1+1, x2, y2-1, fg, bg)
// Now the percent indicator
pctY := int(((float64(y2)-float64(y1)-2)*pct)+float64(y1)) + 1
termbox.SetCell(x2, pctY, '▒', fg, bg)
termbox.SetCell(x1, y2, '╚', fg, bg)
FillWithChar('═', x1+1, y2, x2-1, y2, fg, bg)
termbox.SetCell(x2, y2, '╝', fg, bg)
}
func DrawBorderWithTitle(x1, y1, x2, y2 int, title string, fg, bg termbox.Attribute) {
termbox.SetCell(x1, y1, '╔', fg, bg)
DrawStringAtPoint(title, x1+1, y1, fg, bg)
FillWithChar('═', x1+len(title)+1, y1, x2-1, y1, fg, bg)
termbox.SetCell(x2, y1, '╗', fg, bg)
FillWithChar('║', x1, y1+1, x1, y2-1, fg, bg)
FillWithChar('║', x2, y1+1, x2, y2-1, fg, bg)
termbox.SetCell(x1, y2, '╚', fg, bg)
FillWithChar('═', x1+1, y2, x2-1, y2, fg, bg)
termbox.SetCell(x2, y2, '╝', fg, bg)
}
func DrawBorderWithTitleAndPct(x1, y1, x2, y2 int, title string, pct float64, fg, bg termbox.Attribute) {
termbox.SetCell(x1, y1, '╔', fg, bg)
DrawStringAtPoint(title, x1+1, y1, fg, bg)
FillWithChar('═', x1+len(title)+1, y1, x2-1, y1, fg, bg)
termbox.SetCell(x2, y1, '╗', fg, bg)
FillWithChar('║', x1, y1+1, x1, y2-1, fg, bg)
FillWithChar('║', x2, y1+1, x2, y2-1, fg, bg)
// Now the percent indicator
pctY := int(((float64(y2)-float64(y1)-2)*pct)+float64(y1)) + 1
termbox.SetCell(x2, pctY, '▒', fg, bg)
termbox.SetCell(x1, y2, '╚', fg, bg)
FillWithChar('═', x1+1, y2, x2-1, y2, fg, bg)
termbox.SetCell(x2, y2, '╝', fg, bg)
}
// AlignText Aligns the text txt within width characters using the specified alignment
func AlignText(txt string, width int, align TextAlignment) string {
return AlignTextWithFill(txt, width, align, ' ')
}
// AlignTextWithFill Aligns the text txt within width characters using the specified alignment
// filling any spaces with the 'fill' character
func AlignTextWithFill(txt string, width int, align TextAlignment, fill rune) string {
fillChar := string(fill)
numSpaces := width - len(txt)
switch align {
case AlignCenter:
if numSpaces/2 > 0 {
return fmt.Sprintf("%s%s%s",
strings.Repeat(fillChar, numSpaces/2),
txt, strings.Repeat(fillChar, numSpaces/2),
)
}
return txt
case AlignRight:
return fmt.Sprintf("%s%s", strings.Repeat(fillChar, numSpaces), txt)
default:
if numSpaces >= 0 {
return fmt.Sprintf("%s%s", txt, strings.Repeat(fillChar, numSpaces))
}
return txt
}
}
func ToLabel(c termboxControl) (*Label, error) {
v, ok := c.(*Label)
if ok {
return v, nil
}
return nil, errors.New("Control isn't a Label")
}
func ToInputField(c termboxControl) (*InputField, error) {
v, ok := c.(*InputField)
if ok {
return v, nil
}
return nil, errors.New("Control isn't an Input Field")
}
/* More advanced things are in their respective files */