Move Tab to extra
This commit is contained in:
parent
6246586bbd
commit
c30bf1612a
20
block.go
20
block.go
@ -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()
|
||||||
|
}
|
||||||
|
@ -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':
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user