2017-12-15 22:29:21 +08:00
|
|
|
package tview
|
|
|
|
|
2017-12-17 05:48:26 +08:00
|
|
|
import (
|
|
|
|
"github.com/gdamore/tcell"
|
|
|
|
)
|
2017-12-15 22:29:21 +08:00
|
|
|
|
|
|
|
// Characters to draw the box border.
|
|
|
|
const (
|
2017-12-17 05:48:26 +08:00
|
|
|
BoxVertBar = '\u2500'
|
|
|
|
BoxHorBar = '\u2502'
|
|
|
|
BoxTopLeftCorner = '\u250c'
|
|
|
|
BoxTopRightCorner = '\u2510'
|
|
|
|
BoxBottomRightCorner = '\u2518'
|
|
|
|
BoxBottomLeftCorner = '\u2514'
|
|
|
|
BoxDbVertBar = '\u2550'
|
|
|
|
BoxDbHorBar = '\u2551'
|
|
|
|
BoxDbTopLeftCorner = '\u2554'
|
|
|
|
BoxDbTopRightCorner = '\u2557'
|
|
|
|
BoxDbBottomRightCorner = '\u255d'
|
|
|
|
BoxDbBottomLeftCorner = '\u255a'
|
|
|
|
BoxEllipsis = '\u2026'
|
2017-12-15 22:29:21 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// Box implements Rect with a background and optional elements such as a border
|
|
|
|
// and a title.
|
|
|
|
type Box struct {
|
|
|
|
// The position of the rect.
|
|
|
|
x, y, width, height int
|
|
|
|
|
|
|
|
// The box's background color.
|
|
|
|
backgroundColor tcell.Color
|
|
|
|
|
|
|
|
// Whether or not a border is drawn, reducing the box's space for content by
|
|
|
|
// two in width and height.
|
|
|
|
border bool
|
|
|
|
|
|
|
|
// The color of the border.
|
|
|
|
borderColor tcell.Color
|
|
|
|
|
|
|
|
// The title. Only visible if there is a border, too.
|
|
|
|
title string
|
|
|
|
|
|
|
|
// The color of the title.
|
|
|
|
titleColor tcell.Color
|
2017-12-17 05:48:26 +08:00
|
|
|
|
|
|
|
// Provides a way to find out if this box has focus. We always go through
|
|
|
|
// this interface because it may be overriden by implementing classes.
|
|
|
|
focus Focusable
|
|
|
|
|
|
|
|
// Whether or not this box has focus.
|
|
|
|
hasFocus bool
|
2017-12-15 22:29:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewBox returns a Box without a border.
|
|
|
|
func NewBox() *Box {
|
2017-12-17 05:48:26 +08:00
|
|
|
b := &Box{
|
|
|
|
width: 15,
|
|
|
|
height: 10,
|
|
|
|
borderColor: tcell.ColorWhite,
|
|
|
|
titleColor: tcell.ColorWhite,
|
2017-12-15 22:29:21 +08:00
|
|
|
}
|
2017-12-17 05:48:26 +08:00
|
|
|
b.focus = b
|
|
|
|
return b
|
2017-12-15 22:29:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Draw draws this primitive onto the screen.
|
|
|
|
func (b *Box) Draw(screen tcell.Screen) {
|
|
|
|
// Don't draw anything if there is no space.
|
|
|
|
if b.width <= 0 || b.height <= 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
def := tcell.StyleDefault
|
|
|
|
|
|
|
|
// Fill background.
|
|
|
|
background := def.Background(b.backgroundColor)
|
|
|
|
for y := b.y; y < b.y+b.height; y++ {
|
|
|
|
for x := b.x; x < b.x+b.width; x++ {
|
|
|
|
screen.SetContent(x, y, ' ', nil, background)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw border.
|
|
|
|
if b.border && b.width >= 2 && b.height >= 2 {
|
|
|
|
border := background.Foreground(b.borderColor)
|
2017-12-17 05:48:26 +08:00
|
|
|
var vertical, horizontal, topLeft, topRight, bottomLeft, bottomRight rune
|
|
|
|
if b.focus.HasFocus() {
|
|
|
|
vertical = BoxDbVertBar
|
|
|
|
horizontal = BoxDbHorBar
|
|
|
|
topLeft = BoxDbTopLeftCorner
|
|
|
|
topRight = BoxDbTopRightCorner
|
|
|
|
bottomLeft = BoxDbBottomLeftCorner
|
|
|
|
bottomRight = BoxDbBottomRightCorner
|
|
|
|
} else {
|
|
|
|
vertical = BoxVertBar
|
|
|
|
horizontal = BoxHorBar
|
|
|
|
topLeft = BoxTopLeftCorner
|
|
|
|
topRight = BoxTopRightCorner
|
|
|
|
bottomLeft = BoxBottomLeftCorner
|
|
|
|
bottomRight = BoxBottomRightCorner
|
2017-12-15 22:29:21 +08:00
|
|
|
}
|
|
|
|
for x := b.x + 1; x < b.x+b.width-1; x++ {
|
2017-12-17 05:48:26 +08:00
|
|
|
screen.SetContent(x, b.y, vertical, nil, border)
|
|
|
|
screen.SetContent(x, b.y+b.height-1, vertical, nil, border)
|
2017-12-15 22:29:21 +08:00
|
|
|
}
|
|
|
|
for y := b.y + 1; y < b.y+b.height-1; y++ {
|
2017-12-17 05:48:26 +08:00
|
|
|
screen.SetContent(b.x, y, horizontal, nil, border)
|
|
|
|
screen.SetContent(b.x+b.width-1, y, horizontal, nil, border)
|
2017-12-15 22:29:21 +08:00
|
|
|
}
|
2017-12-17 05:48:26 +08:00
|
|
|
screen.SetContent(b.x, b.y, topLeft, nil, border)
|
|
|
|
screen.SetContent(b.x+b.width-1, b.y, topRight, nil, border)
|
|
|
|
screen.SetContent(b.x, b.y+b.height-1, bottomLeft, nil, border)
|
|
|
|
screen.SetContent(b.x+b.width-1, b.y+b.height-1, bottomRight, nil, border)
|
2017-12-15 22:29:21 +08:00
|
|
|
|
|
|
|
// Draw title.
|
|
|
|
if b.title != "" && b.width >= 4 {
|
|
|
|
title := background.Foreground(b.titleColor)
|
|
|
|
x := b.x
|
|
|
|
for index, ch := range b.title {
|
|
|
|
x++
|
|
|
|
if x >= b.x+b.width-1 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if x == b.x+b.width-2 && index < len(b.title)-1 {
|
|
|
|
ch = BoxEllipsis
|
|
|
|
}
|
|
|
|
screen.SetContent(x, b.y, ch, nil, title)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetRect returns the current position of the rectangle, x, y, width, and
|
|
|
|
// height.
|
|
|
|
func (b *Box) GetRect() (int, int, int, int) {
|
|
|
|
return b.x, b.y, b.width, b.height
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetRect sets a new position of the rectangle.
|
|
|
|
func (b *Box) SetRect(x, y, width, height int) {
|
|
|
|
b.x = x
|
|
|
|
b.y = y
|
|
|
|
b.width = width
|
|
|
|
b.height = height
|
|
|
|
}
|
|
|
|
|
|
|
|
// InputHandler returns nil.
|
2017-12-19 03:04:52 +08:00
|
|
|
func (b *Box) InputHandler() func(event *tcell.EventKey, setFocus func(p Primitive)) {
|
2017-12-15 22:29:21 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetBackgroundColor sets the box's background color.
|
|
|
|
func (b *Box) SetBackgroundColor(color tcell.Color) *Box {
|
|
|
|
b.backgroundColor = color
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetBorder sets the flag indicating whether or not the box should have a
|
|
|
|
// border.
|
|
|
|
func (b *Box) SetBorder(show bool) *Box {
|
|
|
|
b.border = show
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetBorderColor sets the box's border color.
|
|
|
|
func (b *Box) SetBorderColor(color tcell.Color) *Box {
|
|
|
|
b.borderColor = color
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetTitle sets the box's title.
|
|
|
|
func (b *Box) SetTitle(title string) *Box {
|
|
|
|
b.title = title
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetTitleColor sets the box's title color.
|
|
|
|
func (b *Box) SetTitleColor(color tcell.Color) *Box {
|
|
|
|
b.titleColor = color
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
|
|
|
// Focus is called when this primitive receives focus.
|
2017-12-19 03:04:52 +08:00
|
|
|
func (b *Box) Focus(delegate func(p Primitive)) {
|
2017-12-15 22:29:21 +08:00
|
|
|
b.hasFocus = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Blur is called when this primitive loses focus.
|
|
|
|
func (b *Box) Blur() {
|
|
|
|
b.hasFocus = false
|
|
|
|
}
|
2017-12-17 05:48:26 +08:00
|
|
|
|
|
|
|
// HasFocus returns whether or not this primitive has focus.
|
|
|
|
func (b *Box) HasFocus() bool {
|
|
|
|
return b.hasFocus
|
|
|
|
}
|