Move Tab to extra

This commit is contained in:
gizak 2015-10-20 21:45:28 -04:00
parent 6246586bbd
commit c30bf1612a
3 changed files with 101 additions and 76 deletions

View File

@ -140,3 +140,23 @@ func (d *Block) chopOverflow(ps []Point) []Point {
} }
return nps return nps
} }
func (b Block) InnerWidth() int {
return b.innerWidth
}
func (b Block) InnerHeight() int {
return b.innerHeight
}
func (b Block) InnerX() int {
return b.innerX
}
func (b Block) InnerY() int {
return b.innerY
}
func (b *Block) Align() {
b.align()
}

View File

@ -1,15 +1,16 @@
package main package main
import ( import (
"github.com/marigs/termui" "github.com/gizak/termui"
"github.com/gizak/termui/extra"
) )
func main() { func main() {
err := termui.Init() err := termui.Init()
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer termui.Close() defer termui.Close()
termui.UseTheme("helloworld") termui.UseTheme("helloworld")
@ -19,7 +20,7 @@ func main() {
header.HasBorder = false header.HasBorder = false
header.TextBgColor = termui.ColorBlue header.TextBgColor = termui.ColorBlue
tab1 := termui.NewTab("pierwszy") tab1 := extra.NewTab("pierwszy")
par2 := termui.NewPar("Press q to quit\nPress j or k to switch tabs\n") par2 := termui.NewPar("Press q to quit\nPress j or k to switch tabs\n")
par2.Height = 5 par2.Height = 5
par2.Width = 37 par2.Width = 37
@ -28,7 +29,7 @@ func main() {
par2.Border.FgColor = termui.ColorYellow par2.Border.FgColor = termui.ColorYellow
tab1.AddBlocks(par2) tab1.AddBlocks(par2)
tab2 := termui.NewTab("drugi") tab2 := extra.NewTab("drugi")
bc := termui.NewBarChart() bc := termui.NewBarChart()
data := []int{3, 2, 5, 3, 9, 5, 3, 2, 5, 8, 3, 2, 4, 5, 3, 2, 5, 7, 5, 3, 2, 6, 7, 4, 6, 3, 6, 7, 8, 3, 6, 4, 5, 3, 2, 4, 6, 4, 8, 5, 9, 4, 3, 6, 5, 3, 6} data := []int{3, 2, 5, 3, 9, 5, 3, 2, 5, 8, 3, 2, 4, 5, 3, 2, 5, 7, 5, 3, 2, 6, 7, 4, 6, 3, 6, 7, 8, 3, 6, 4, 5, 3, 2, 4, 6, 4, 8, 5, 9, 4, 3, 6, 5, 3, 6}
bclabels := []string{"S0", "S1", "S2", "S3", "S4", "S5"} bclabels := []string{"S0", "S1", "S2", "S3", "S4", "S5"}
@ -42,24 +43,25 @@ func main() {
bc.NumColor = termui.ColorYellow bc.NumColor = termui.ColorYellow
tab2.AddBlocks(bc) tab2.AddBlocks(bc)
tab3 := termui.NewTab("trzeci") tab3 := extra.NewTab("trzeci")
tab4 := termui.NewTab("żółw") tab4 := extra.NewTab("żółw")
tab5 := termui.NewTab("four") tab5 := extra.NewTab("four")
tab6 := termui.NewTab("five") tab6 := extra.NewTab("five")
tabpane := termui.NewTabpane() tabpane := extra.NewTabpane()
tabpane.Y = 1 tabpane.Y = 1
tabpane.Width = 30 tabpane.Width = 30
tabpane.HasBorder = true tabpane.HasBorder = true
tabpane.SetTabs(*tab1, *tab2, *tab3, *tab4, *tab5, *tab6) tabpane.SetTabs(*tab1, *tab2, *tab3, *tab4, *tab5, *tab6)
termui.Render(header, tabpane)
evt := termui.EventCh() evt := termui.EventCh()
termui.Render(header, tabpane)
for { for {
select { select {
case e := <- evt: case e := <-evt:
if e.Type == termui.EventKey { if e.Type == termui.EventKey {
switch e.Ch { switch e.Ch {
case 'q': case 'q':

View File

@ -1,51 +1,54 @@
package extra
package termui
import ( import (
"unicode/utf8" "unicode/utf8"
. "github.com/gizak/termui"
) )
type Tab struct { type Tab struct {
Label string Label string
RuneLen int RuneLen int
Blocks []Bufferer Blocks []Bufferer
} }
func NewTab(label string) *Tab { func NewTab(label string) *Tab {
return &Tab { return &Tab{
Label: label, Label: label,
RuneLen: utf8.RuneCount([]byte(label)) } RuneLen: utf8.RuneCount([]byte(label))}
} }
func (tab *Tab) AddBlocks(rs ...Bufferer) { func (tab *Tab) AddBlocks(rs ...Bufferer) {
for _, r := range rs { for _, r := range rs {
tab.Blocks = append(tab.Blocks, r) tab.Blocks = append(tab.Blocks, r)
} }
} }
func (tab *Tab) Buffer() []Point { func (tab *Tab) Buffer() []Point {
points := []Point{} points := []Point{}
for blockNum := 0; blockNum < len(tab.Blocks); blockNum++ { for blockNum := 0; blockNum < len(tab.Blocks); blockNum++ {
b := &tab.Blocks[blockNum] b := &tab.Blocks[blockNum]
blockPoints := (*b).Buffer() blockPoints := (*b).Buffer()
points = append(points, blockPoints...) points = append(points, blockPoints...)
} }
return points return points
} }
type Tabpane struct { type Tabpane struct {
Block Block
Tabs []Tab Tabs []Tab
activeTabIndex int activeTabIndex int
posTabText []int ActiveTabBg Attribute
offTabText int posTabText []int
offTabText int
} }
func NewTabpane() *Tabpane { func NewTabpane() *Tabpane {
tp := Tabpane { tp := Tabpane{
Block: *NewBlock(), Block: *NewBlock(),
activeTabIndex: 0, activeTabIndex: 0,
offTabText: 0} offTabText: 0,
ActiveTabBg: Theme().TabActiveBg}
return &tp return &tp
} }
@ -53,19 +56,19 @@ func (tp *Tabpane) SetTabs(tabs ...Tab) {
tp.Tabs = make([]Tab, len(tabs)) tp.Tabs = make([]Tab, len(tabs))
tp.posTabText = make([]int, len(tabs)+1) tp.posTabText = make([]int, len(tabs)+1)
off := 0 off := 0
for i :=0; i < len(tp.Tabs); i++ { for i := 0; i < len(tp.Tabs); i++ {
tp.Tabs[i] = tabs[i] tp.Tabs[i] = tabs[i]
tp.posTabText[i] = off tp.posTabText[i] = off
off += tp.Tabs[i].RuneLen+1 //+1 for space between tabs off += tp.Tabs[i].RuneLen + 1 //+1 for space between tabs
} }
tp.posTabText[len(tabs)] = off-1 //total length of Tab's text tp.posTabText[len(tabs)] = off - 1 //total length of Tab's text
} }
func (tp *Tabpane) SetActiveLeft() { func (tp *Tabpane) SetActiveLeft() {
if tp.activeTabIndex == 0 { if tp.activeTabIndex == 0 {
return return
} }
tp.activeTabIndex -= 1 tp.activeTabIndex -= 1
if tp.posTabText[tp.activeTabIndex] < tp.offTabText { if tp.posTabText[tp.activeTabIndex] < tp.offTabText {
tp.offTabText = tp.posTabText[tp.activeTabIndex] tp.offTabText = tp.posTabText[tp.activeTabIndex]
} }
@ -75,10 +78,10 @@ func (tp *Tabpane) SetActiveRight() {
if tp.activeTabIndex == len(tp.Tabs)-1 { if tp.activeTabIndex == len(tp.Tabs)-1 {
return return
} }
tp.activeTabIndex += 1 tp.activeTabIndex += 1
endOffset := tp.posTabText[tp.activeTabIndex] + tp.Tabs[tp.activeTabIndex].RuneLen endOffset := tp.posTabText[tp.activeTabIndex] + tp.Tabs[tp.activeTabIndex].RuneLen
if endOffset + tp.offTabText > tp.innerWidth { if endOffset+tp.offTabText > tp.InnerWidth() {
tp.offTabText = endOffset - tp.innerWidth tp.offTabText = endOffset - tp.InnerWidth()
} }
} }
@ -92,7 +95,7 @@ func (tp *Tabpane) checkAlignment() int {
if tp.offTabText > 0 { if tp.offTabText > 0 {
ret = -1 ret = -1
} }
if tp.offTabText + tp.innerWidth < tp.posTabText[len(tp.Tabs)] { if tp.offTabText+tp.InnerWidth() < tp.posTabText[len(tp.Tabs)] {
ret += 1 ret += 1
} }
return ret return ret
@ -100,13 +103,14 @@ func (tp *Tabpane) checkAlignment() int {
// Checks if all tabs fits innerWidth of Tabpane // Checks if all tabs fits innerWidth of Tabpane
func (tp *Tabpane) fitsWidth() bool { func (tp *Tabpane) fitsWidth() bool {
return tp.innerWidth >= tp.posTabText[len(tp.Tabs)] return tp.InnerWidth() >= tp.posTabText[len(tp.Tabs)]
} }
func (tp *Tabpane) align() { func (tp *Tabpane) align() {
if !tp.fitsWidth() && !tp.HasBorder { if !tp.fitsWidth() && !tp.HasBorder {
tp.innerWidth -= 2 tp.PaddingLeft += 1
tp.innerX += 1 tp.PaddingRight += 1
tp.Block.Align()
} }
} }
@ -114,11 +118,11 @@ func (tp *Tabpane) align() {
// Point can be invisible if concatenation of Tab's texts is widther then // Point can be invisible if concatenation of Tab's texts is widther then
// innerWidth of Tabpane // innerWidth of Tabpane
func (tp *Tabpane) addPoint(ptab []Point, charOffset *int, oftX *int, points ...Point) []Point { func (tp *Tabpane) addPoint(ptab []Point, charOffset *int, oftX *int, points ...Point) []Point {
if *charOffset < tp.offTabText || tp.offTabText + tp.innerWidth < *charOffset { if *charOffset < tp.offTabText || tp.offTabText+tp.InnerWidth() < *charOffset {
*charOffset++ *charOffset++
return ptab return ptab
} }
for _, p := range(points) { for _, p := range points {
p.X = *oftX p.X = *oftX
ptab = append(ptab, p) ptab = append(ptab, p)
} }
@ -133,14 +137,14 @@ func (tp *Tabpane) drawPointWithBorder(p Point, ch rune, chbord rune, chdown run
p.Ch = ch p.Ch = ch
if tp.HasBorder { if tp.HasBorder {
p.Ch = chdown p.Ch = chdown
p.Y = tp.innerY-1 p.Y = tp.InnerY() - 1
addp = append(addp, p) addp = append(addp, p)
p.Ch = chup p.Ch = chup
p.Y = tp.innerY+1 p.Y = tp.InnerY() + 1
addp = append(addp, p) addp = append(addp, p)
p.Ch = chbord p.Ch = chbord
} }
p.Y = tp.innerY p.Y = tp.InnerY()
return append(addp, p) return append(addp, p)
} }
@ -151,41 +155,41 @@ func (tp *Tabpane) Buffer() []Point {
tp.Height = 1 tp.Height = 1
} }
if tp.Width > tp.posTabText[len(tp.Tabs)]+2 { if tp.Width > tp.posTabText[len(tp.Tabs)]+2 {
tp.Width = tp.posTabText[len(tp.Tabs)]+2 tp.Width = tp.posTabText[len(tp.Tabs)] + 2
} }
ps := tp.Block.Buffer() ps := tp.Block.Buffer()
tp.align() tp.align()
if tp.innerHeight <= 0 || tp.innerWidth <= 0 { if tp.InnerHeight() <= 0 || tp.InnerWidth() <= 0 {
return nil return nil
} }
oftX := tp.innerX oftX := tp.InnerX()
charOffset := 0 charOffset := 0
pt := Point{Bg: tp.Border.BgColor, Fg: tp.Border.FgColor} pt := Point{Bg: tp.Border.BgColor, Fg: tp.Border.FgColor}
for i, tab := range tp.Tabs { for i, tab := range tp.Tabs {
if i != 0 { if i != 0 {
pt.X = oftX pt.X = oftX
pt.Y = tp.innerY pt.Y = tp.InnerY()
addp := tp.drawPointWithBorder(pt, ' ', VERTICAL_LINE, HORIZONTAL_DOWN, HORIZONTAL_UP) addp := tp.drawPointWithBorder(pt, ' ', VERTICAL_LINE, HORIZONTAL_DOWN, HORIZONTAL_UP)
ps = tp.addPoint(ps, &charOffset, &oftX, addp...) ps = tp.addPoint(ps, &charOffset, &oftX, addp...)
} }
if i == tp.activeTabIndex { if i == tp.activeTabIndex {
pt.Bg = theme.TabActiveBg pt.Bg = tp.ActiveTabBg
} }
rs := str2runes(tab.Label) rs := []rune(tab.Label)
for k := 0; k < len(rs); k++ { for k := 0; k < len(rs); k++ {
addp := make([]Point, 0, 2) addp := make([]Point, 0, 2)
if i == tp.activeTabIndex && tp.HasBorder { if i == tp.activeTabIndex && tp.HasBorder {
pt.Ch = ' ' pt.Ch = ' '
pt.Y = tp.innerY + 1 pt.Y = tp.InnerY() + 1
pt.Bg = tp.Border.BgColor pt.Bg = tp.Border.BgColor
addp = append(addp, pt) addp = append(addp, pt)
pt.Bg = theme.TabActiveBg pt.Bg = tp.ActiveTabBg
} }
pt.Y = tp.innerY pt.Y = tp.InnerY()
pt.Ch = rs[k] pt.Ch = rs[k]
addp = append(addp, pt) addp = append(addp, pt)
@ -195,7 +199,7 @@ func (tp *Tabpane) Buffer() []Point {
if !tp.fitsWidth() { if !tp.fitsWidth() {
all := tp.checkAlignment() all := tp.checkAlignment()
pt.X = tp.innerX-1 pt.X = tp.InnerX() - 1
pt.Ch = '*' pt.Ch = '*'
if tp.HasBorder { if tp.HasBorder {
@ -208,7 +212,7 @@ func (tp *Tabpane) Buffer() []Point {
ps = append(ps, addp...) ps = append(ps, addp...)
} }
pt.X = tp.innerX + tp.innerWidth pt.X = tp.InnerX() + tp.InnerWidth()
pt.Ch = '*' pt.Ch = '*'
if tp.HasBorder { if tp.HasBorder {
pt.Ch = VERTICAL_LINE pt.Ch = VERTICAL_LINE
@ -221,8 +225,8 @@ func (tp *Tabpane) Buffer() []Point {
} }
//draw tab content below the Tabpane //draw tab content below the Tabpane
if i == tp.activeTabIndex { if i == tp.activeTabIndex {
blockPoints := tab.Buffer() blockPoints := tab.Buffer()
for i := 0; i < len(blockPoints); i++ { for i := 0; i < len(blockPoints); i++ {
blockPoints[i].Y += tp.Height + tp.Y blockPoints[i].Y += tp.Height + tp.Y
} }
@ -232,4 +236,3 @@ func (tp *Tabpane) Buffer() []Point {
return ps return ps
} }