Add gauge and list component

This commit is contained in:
gizak 2015-02-03 20:56:49 -05:00
parent ddc86587d8
commit cc6b38d600
8 changed files with 216 additions and 75 deletions

View File

@ -1,14 +1,12 @@
package termui
import tm "github.com/nsf/termbox-go"
type Div struct {
type Block struct {
X int
Y int
Border LabeledBox
Border labeledBorder
IsDisplay bool
HasBorder bool
BgColor tm.Attribute
BgColor Attribute
Width int
Height int
innerWidth int
@ -17,21 +15,16 @@ type Div struct {
innerY int
}
func NewDiv() Div {
d := Div{}
d.Border.BgColor = tm.ColorDefault
d.Border.FgColor = tm.ColorDefault
d.Border.LabelFgColor = tm.ColorDefault
d.Border.LabelBgColor = tm.ColorDefault
func NewBlock() *Block {
d := Block{}
d.IsDisplay = true
d.HasBorder = true
d.Width = 2
d.Height = 2
d.BgColor = tm.ColorDefault
return d
return &d
}
func (d *Div) sync() {
func (d *Block) align() {
d.innerWidth = d.Width
d.innerHeight = d.Height
d.innerX = d.X
@ -49,8 +42,8 @@ func (d *Div) sync() {
}
}
func (d Div) Buffer() []Point {
(&d).sync()
func (d *Block) Buffer() []Point {
d.align()
ps := []Point{}
if !d.IsDisplay {
@ -67,7 +60,7 @@ func (d Div) Buffer() []Point {
p.X = d.X + 1 + i
p.Y = d.Y + 1 + j
p.Code.Ch = ' '
p.Code.Bg = d.BgColor
p.Code.Bg = toTmAttr(d.BgColor)
ps = append(ps, p)
}
}

74
box.go
View File

@ -1,7 +1,5 @@
package termui
import tm "github.com/nsf/termbox-go"
const TOP_RIGHT = '┐'
const VERTICAL_LINE = '│'
const HORIZONTAL_LINE = '─'
@ -9,56 +7,56 @@ const TOP_LEFT = '┌'
const BOTTOM_RIGHT = '┘'
const BOTTOM_LEFT = '└'
type Box struct {
type border struct {
X int
Y int
Width int
Height int
FgColor tm.Attribute
BgColor tm.Attribute
FgColor Attribute
BgColor Attribute
}
type HLine struct {
type hline struct {
X int
Y int
Length int
FgColor tm.Attribute
BgColor tm.Attribute
FgColor Attribute
BgColor Attribute
}
type VLine struct {
type vline struct {
X int
Y int
Length int
FgColor tm.Attribute
BgColor tm.Attribute
FgColor Attribute
BgColor Attribute
}
func (l HLine) Buffer() []Point {
func (l hline) Buffer() []Point {
pts := make([]Point, l.Length)
for i := 0; i < l.Length; i++ {
pts[i].X = l.X + i
pts[i].Y = l.Y
pts[i].Code.Ch = HORIZONTAL_LINE
pts[i].Code.Bg = l.BgColor
pts[i].Code.Fg = l.FgColor
pts[i].Code.Bg = toTmAttr(l.BgColor)
pts[i].Code.Fg = toTmAttr(l.FgColor)
}
return pts
}
func (l VLine) Buffer() []Point {
func (l vline) Buffer() []Point {
pts := make([]Point, l.Length)
for i := 0; i < l.Length; i++ {
pts[i].X = l.X
pts[i].Y = l.Y + i
pts[i].Code.Ch = VERTICAL_LINE
pts[i].Code.Bg = l.BgColor
pts[i].Code.Fg = l.FgColor
pts[i].Code.Bg = toTmAttr(l.BgColor)
pts[i].Code.Fg = toTmAttr(l.FgColor)
}
return pts
}
func (b Box) Buffer() []Point {
func (b border) Buffer() []Point {
if b.Width < 2 || b.Height < 2 {
return nil
}
@ -66,45 +64,45 @@ func (b Box) Buffer() []Point {
pts[0].X = b.X
pts[0].Y = b.Y
pts[0].Code.Fg = b.FgColor
pts[0].Code.Bg = b.BgColor
pts[0].Code.Fg = toTmAttr(b.FgColor)
pts[0].Code.Bg = toTmAttr(b.BgColor)
pts[0].Code.Ch = TOP_LEFT
pts[1].X = b.X + b.Width - 1
pts[1].Y = b.Y
pts[1].Code.Fg = b.FgColor
pts[1].Code.Bg = b.BgColor
pts[1].Code.Fg = toTmAttr(b.FgColor)
pts[1].Code.Bg = toTmAttr(b.BgColor)
pts[1].Code.Ch = TOP_RIGHT
pts[2].X = b.X
pts[2].Y = b.Y + b.Height - 1
pts[2].Code.Fg = b.FgColor
pts[2].Code.Bg = b.BgColor
pts[2].Code.Fg = toTmAttr(b.FgColor)
pts[2].Code.Bg = toTmAttr(b.BgColor)
pts[2].Code.Ch = BOTTOM_LEFT
pts[3].X = b.X + b.Width - 1
pts[3].Y = b.Y + b.Height - 1
pts[3].Code.Fg = b.FgColor
pts[3].Code.Bg = b.BgColor
pts[3].Code.Fg = toTmAttr(b.FgColor)
pts[3].Code.Bg = toTmAttr(b.BgColor)
pts[3].Code.Ch = BOTTOM_RIGHT
copy(pts[4:], (HLine{b.X + 1, b.Y, b.Width - 2, b.FgColor, b.BgColor}).Buffer())
copy(pts[4+b.Width-2:], (HLine{b.X + 1, b.Y + b.Height - 1, b.Width - 2, b.FgColor, b.BgColor}).Buffer())
copy(pts[4+2*b.Width-4:], (VLine{b.X, b.Y + 1, b.Height - 2, b.FgColor, b.BgColor}).Buffer())
copy(pts[4+2*b.Width-4+b.Height-2:], (VLine{b.X + b.Width - 1, b.Y + 1, b.Height - 2, b.FgColor, b.BgColor}).Buffer())
copy(pts[4:], (hline{b.X + 1, b.Y, b.Width - 2, b.FgColor, b.BgColor}).Buffer())
copy(pts[4+b.Width-2:], (hline{b.X + 1, b.Y + b.Height - 1, b.Width - 2, b.FgColor, b.BgColor}).Buffer())
copy(pts[4+2*b.Width-4:], (vline{b.X, b.Y + 1, b.Height - 2, b.FgColor, b.BgColor}).Buffer())
copy(pts[4+2*b.Width-4+b.Height-2:], (vline{b.X + b.Width - 1, b.Y + 1, b.Height - 2, b.FgColor, b.BgColor}).Buffer())
return pts
}
type LabeledBox struct {
Box
type labeledBorder struct {
border
Label string
LabelFgColor tm.Attribute
LabelBgColor tm.Attribute
LabelFgColor Attribute
LabelBgColor Attribute
}
func (lb LabeledBox) Buffer() []Point {
ps := lb.Box.Buffer()
func (lb labeledBorder) Buffer() []Point {
ps := lb.border.Buffer()
maxTxtW := lb.Width - 2
rs := trimStr2Runes(lb.Label, maxTxtW)
@ -113,8 +111,8 @@ func (lb LabeledBox) Buffer() []Point {
p.X = lb.X + 1 + i
p.Y = lb.Y
p.Code.Ch = rs[i]
p.Code.Fg = lb.LabelFgColor
p.Code.Bg = lb.LabelBgColor
p.Code.Fg = toTmAttr(lb.LabelFgColor)
p.Code.Bg = toTmAttr(lb.LabelBgColor)
ps = append(ps, p)
}

56
gauge.go Normal file
View File

@ -0,0 +1,56 @@
package termui
import "strconv"
type Gauge struct {
Block
Percent int
BarColor Attribute
PercentColor Attribute
}
func NewGauge() *Gauge {
g := &Gauge{Block: *NewBlock(), PercentColor: ColorWhite, BarColor: ColorGreen}
g.Width = 12
g.Height = 5
return g
}
func (g *Gauge) Buffer() []Point {
ps := g.Block.Buffer()
w := g.Percent * g.innerWidth / 100
s := strconv.Itoa(g.Percent) + "%"
rs := str2runes(s)
prx := g.innerX + g.innerWidth/2 - 1
pry := g.innerY + g.innerHeight/2
// plot bar
for i := 0; i < g.innerHeight; i++ {
for j := 0; j < w; j++ {
p := Point{}
p.X = g.innerX + j
p.Y = g.innerY + i
p.Code.Ch = ' '
p.Code.Bg = toTmAttr(g.BarColor)
ps = append(ps, p)
}
}
// plot percentage
for i, v := range rs {
p := Point{}
p.X = prx + i
p.Y = pry
p.Code.Ch = v
p.Code.Fg = toTmAttr(g.PercentColor)
if w > g.innerWidth/2-1+i {
p.Code.Bg = toTmAttr(g.BarColor)
} else {
p.Code.Bg = toTmAttr(g.Block.BgColor)
}
ps = append(ps, p)
}
return ps
}

View File

@ -2,6 +2,31 @@ package termui
import "unicode/utf8"
import "strings"
import tm "github.com/nsf/termbox-go"
type Attribute uint16
const (
ColorDefault Attribute = iota
ColorBlack
ColorRed
ColorGreen
ColorYellow
ColorBlue
ColorMagenta
ColorCyan
ColorWhite
)
const (
AttrBold Attribute = 1 << (iota + 9)
AttrUnderline
AttrReverse
)
func toTmAttr(x Attribute) tm.Attribute {
return tm.Attribute(x)
}
func str2runes(s string) []rune {
n := utf8.RuneCountInString(s)

71
list.go Normal file
View File

@ -0,0 +1,71 @@
package termui
import "strings"
type List struct {
Block
Items []string
Overflow string
ItemFgColor Attribute
ItemBgColor Attribute
}
func NewList() *List {
l := &List{Block: *NewBlock()}
l.Overflow = "hidden"
return l
}
func (l *List) Buffer() []Point {
ps := l.Block.Buffer()
switch l.Overflow {
case "wrap":
rs := str2runes(strings.Join(l.Items, "\n"))
i, j, k := 0, 0, 0
for i < l.innerHeight && k < len(rs) {
if rs[k] == '\n' || j == l.innerWidth {
i++
j = 0
if rs[k] == '\n' {
k++
}
continue
}
pi := Point{}
pi.X = l.innerX + j
pi.Y = l.innerY + i
pi.Code.Ch = rs[k]
pi.Code.Bg = toTmAttr(l.ItemBgColor)
pi.Code.Fg = toTmAttr(l.ItemFgColor)
ps = append(ps, pi)
k++
j++
}
case "hidden":
trimItems := l.Items
if len(trimItems) > l.innerHeight {
trimItems = trimItems[:l.innerHeight]
}
for i, v := range trimItems {
rs := trimStr2Runes(v, l.innerWidth)
j := 0
for _, vv := range rs {
p := Point{}
p.X = l.innerX + j
p.Y = l.innerY + i
p.Code.Ch = vv
p.Code.Bg = toTmAttr(l.ItemBgColor)
p.Code.Fg = toTmAttr(l.ItemFgColor)
ps = append(ps, p)
j++
}
}
}
return ps
}

22
p.go
View File

@ -1,22 +1,18 @@
package termui
import tm "github.com/nsf/termbox-go"
type P struct {
Div
Block
Text string
TextFgColor tm.Attribute
TextBgColor tm.Attribute
TextFgColor Attribute
TextBgColor Attribute
}
func NewP(s string) P {
return P{Div: NewDiv(), Text: s}
func NewP(s string) *P {
return &P{Block: *NewBlock(), Text: s}
}
func (p P) Buffer() []Point {
ps := p.Div.Buffer()
(&p).sync()
func (p *P) Buffer() []Point {
ps := p.Block.Buffer()
rs := str2runes(p.Text)
i, j, k := 0, 0, 0
@ -34,8 +30,8 @@ func (p P) Buffer() []Point {
pi.Y = p.innerY + i
pi.Code.Ch = rs[k]
pi.Code.Bg = p.TextBgColor
pi.Code.Fg = p.TextFgColor
pi.Code.Bg = toTmAttr(p.TextBgColor)
pi.Code.Fg = toTmAttr(p.TextFgColor)
ps = append(ps, pi)
k++

View File

@ -4,6 +4,6 @@ import tm "github.com/nsf/termbox-go"
type Point struct {
Code tm.Cell
X int
Y int
X int
Y int
}

View File

@ -10,14 +10,16 @@ func Init() error {
return tm.Init()
}
func Close(){
func Close() {
tm.Close()
}
func Render(r Renderer) {
buf := r.Buffer()
for _,v := range buf {
tm.SetCell(v.X,v.Y,v.Code.Ch,v.Code.Fg,v.Code.Bg)
func Render(rs ...Renderer) {
for _, r := range rs {
buf := r.Buffer()
for _, v := range buf {
tm.SetCell(v.X, v.Y, v.Code.Ch, v.Code.Fg, v.Code.Bg)
}
}
tm.Flush()
}