forked from tslocum/cview
WIP implementation of table cell padding
This commit is contained in:
parent
1513847ae3
commit
20b34dda65
|
@ -250,6 +250,9 @@ const tableSelectCell = `[green]func[white] [yellow]main[white]() {
|
|||
// Table demonstrates the Table.
|
||||
func Table(nextSlide func()) (title string, content cview.Primitive) {
|
||||
table := cview.NewTable()
|
||||
table.SetSeparator('|')
|
||||
table.SetCellBorders(true)
|
||||
table.SetCellPadding(1, 4)
|
||||
table.SetFixed(1, 1)
|
||||
for row, line := range strings.Split(tableData, "\n") {
|
||||
for column, cell := range strings.Split(line, "|") {
|
||||
|
|
6
go.mod
6
go.mod
|
@ -1,13 +1,13 @@
|
|||
module gitlab.com/tslocum/cview
|
||||
|
||||
go 1.12
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201109052606-7d87d8188c8d
|
||||
github.com/gdamore/tcell/v2 v2.0.0
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3
|
||||
github.com/mattn/go-runewidth v0.0.9
|
||||
github.com/rivo/uniseg v0.2.0
|
||||
gitlab.com/tslocum/cbind v0.1.4
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435 // indirect
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
|
||||
golang.org/x/text v0.3.4 // indirect
|
||||
)
|
||||
|
|
9
go.sum
9
go.sum
|
@ -1,8 +1,8 @@
|
|||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell/v2 v2.0.0-dev/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201109052606-7d87d8188c8d h1:C1FQEuzw5kUUveSXpZp3v0+qOR+VEnzHsQ7K6n39LsM=
|
||||
github.com/gdamore/tcell/v2 v2.0.1-0.20201109052606-7d87d8188c8d/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/gdamore/tcell/v2 v2.0.0 h1:GRWG8aLfWAlekj9Q6W29bVvkHENc6hp79XOqG4AWDOs=
|
||||
github.com/gdamore/tcell/v2 v2.0.0/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
|
@ -13,9 +13,10 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
|||
gitlab.com/tslocum/cbind v0.1.4 h1:cbZXPPcieXspk8cShoT6efz7HAT8yMNQcofYWNizis4=
|
||||
gitlab.com/tslocum/cbind v0.1.4/go.mod h1:RvwYE3auSjBNlCmWeGspzn+jdLUVQ8C2QGC+0nP9ChI=
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb h1:HS9IzC4UFbpMBLQUDSQcU+ViVT1vdFCQVjdPVpTlZrs=
|
||||
golang.org/x/sys v0.0.0-20201013132646-2da7054afaeb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk=
|
||||
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
|
188
table.go
188
table.go
|
@ -2,6 +2,7 @@ package cview
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
|
@ -263,14 +264,17 @@ type Table struct {
|
|||
*Box
|
||||
|
||||
// Whether or not this table has borders around each cell.
|
||||
borders bool
|
||||
cellBorders bool
|
||||
|
||||
// The color of the borders or the separator.
|
||||
bordersColor tcell.Color
|
||||
// The color of the cell borders or the separator.
|
||||
cellBorderColor tcell.Color
|
||||
|
||||
// If there are no borders, the column separator.
|
||||
separator rune
|
||||
|
||||
// The size of the padding between each cell.
|
||||
rowPadding, columnPadding int
|
||||
|
||||
// The cells of the table. Rows first, then columns.
|
||||
cells [][]*TableCell
|
||||
|
||||
|
@ -353,7 +357,7 @@ func NewTable() *Table {
|
|||
Box: NewBox(),
|
||||
scrollBarVisibility: ScrollBarAuto,
|
||||
scrollBarColor: Styles.ScrollBarColor,
|
||||
bordersColor: Styles.GraphicsColor,
|
||||
cellBorderColor: Styles.GraphicsColor,
|
||||
separator: ' ',
|
||||
sortClicked: true,
|
||||
lastColumn: -1,
|
||||
|
@ -369,23 +373,6 @@ func (t *Table) Clear() {
|
|||
t.lastColumn = -1
|
||||
}
|
||||
|
||||
// SetBorders sets whether or not each cell in the table is surrounded by a
|
||||
// border.
|
||||
func (t *Table) SetBorders(show bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.borders = show
|
||||
}
|
||||
|
||||
// SetBordersColor sets the color of the cell borders.
|
||||
func (t *Table) SetBordersColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.bordersColor = color
|
||||
}
|
||||
|
||||
// SetScrollBarVisibility specifies the display of the scroll bar.
|
||||
func (t *Table) SetScrollBarVisibility(visibility ScrollBarVisibility) {
|
||||
t.Lock()
|
||||
|
@ -430,6 +417,30 @@ func (t *Table) SetSeparator(separator rune) {
|
|||
t.separator = separator
|
||||
}
|
||||
|
||||
// SetCellBorders sets whether or not each cell is surrounded by a border.
|
||||
func (t *Table) SetCellBorders(show bool) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.cellBorders = show
|
||||
}
|
||||
|
||||
// SetCellBorderColor sets the color of the cell borders.
|
||||
func (t *Table) SetCellBorderColor(color tcell.Color) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.cellBorderColor = color
|
||||
}
|
||||
|
||||
// SetCellPadding sets the size of the padding between each cell.
|
||||
func (t *Table) SetCellPadding(row, column int) {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
|
||||
t.rowPadding, t.columnPadding = row, column
|
||||
}
|
||||
|
||||
// SetFixed sets the number of fixed rows and columns which are always visible
|
||||
// even when the rest of the cells are scrolled out of view. Rows are always the
|
||||
// top-most ones. Columns are always the left-most ones.
|
||||
|
@ -694,7 +705,7 @@ func (t *Table) cellAt(x, y int) (row, column int) {
|
|||
rectX, rectY, _, _ := t.GetInnerRect()
|
||||
|
||||
// Determine row as seen on screen.
|
||||
if t.borders {
|
||||
if t.cellBorders {
|
||||
row = (y - rectY - 1) / 2
|
||||
} else {
|
||||
row = y - rectY
|
||||
|
@ -714,7 +725,7 @@ func (t *Table) cellAt(x, y int) (row, column int) {
|
|||
column = -1
|
||||
if x >= rectX {
|
||||
columnX := rectX
|
||||
if t.borders {
|
||||
if t.cellBorders {
|
||||
columnX++
|
||||
}
|
||||
for index, width := range t.visibleColumnWidths {
|
||||
|
@ -815,7 +826,7 @@ func (t *Table) Draw(screen tcell.Screen) {
|
|||
|
||||
// What's our available screen space?
|
||||
x, y, width, height := t.GetInnerRect()
|
||||
if t.borders {
|
||||
if t.cellBorders {
|
||||
t.visibleRows = height / 2
|
||||
} else {
|
||||
t.visibleRows = height
|
||||
|
@ -861,9 +872,10 @@ func (t *Table) Draw(screen tcell.Screen) {
|
|||
t.rowOffset = t.selectedRow - t.fixedRows
|
||||
t.trackEnd = false
|
||||
}
|
||||
if t.borders {
|
||||
if 2*(t.selectedRow+1-t.rowOffset) >= height {
|
||||
t.rowOffset = t.selectedRow + 1 - height/2
|
||||
if t.cellBorders {
|
||||
if 2*(t.rowPadding+t.selectedRow+1-t.rowOffset) >= height {
|
||||
log.Fatal("test")
|
||||
t.rowOffset = t.selectedRow + 1
|
||||
t.trackEnd = false
|
||||
}
|
||||
} else {
|
||||
|
@ -873,18 +885,18 @@ func (t *Table) Draw(screen tcell.Screen) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if t.borders {
|
||||
if 2*(len(t.cells)-t.rowOffset) < height {
|
||||
if t.cellBorders {
|
||||
if 2*(len(t.cells)-t.rowOffset)*t.rowPadding < height {
|
||||
t.trackEnd = true
|
||||
}
|
||||
} else {
|
||||
if len(t.cells)-t.rowOffset < height {
|
||||
if 2*(t.rowPadding+len(t.cells)-t.rowOffset) < height {
|
||||
t.trackEnd = true
|
||||
}
|
||||
}
|
||||
if t.trackEnd {
|
||||
if t.borders {
|
||||
t.rowOffset = len(t.cells) - height/2
|
||||
if t.cellBorders {
|
||||
t.rowOffset = len(t.cells) + height/(2*(t.rowPadding+1))
|
||||
} else {
|
||||
t.rowOffset = len(t.cells) - height
|
||||
}
|
||||
|
@ -912,10 +924,11 @@ func (t *Table) Draw(screen tcell.Screen) {
|
|||
tableHeight, tableWidth int
|
||||
)
|
||||
rowStep := 1
|
||||
if t.borders {
|
||||
if t.cellBorders {
|
||||
rowStep = 2 // With borders, every table row takes two screen rows.
|
||||
tableWidth = 1 // We start at the second character because of the left table border.
|
||||
}
|
||||
rowStep += t.rowPadding
|
||||
if t.evaluateAllRows {
|
||||
allRows = make([]int, len(t.cells))
|
||||
for row := range t.cells {
|
||||
|
@ -1026,41 +1039,75 @@ ColumnLoop:
|
|||
}
|
||||
|
||||
// Helper function which draws border runes.
|
||||
borderStyle := tcell.StyleDefault.Background(t.backgroundColor).Foreground(t.bordersColor)
|
||||
borderStyle := tcell.StyleDefault.Background(t.backgroundColor).Foreground(t.cellBorderColor)
|
||||
drawBorder := func(colX, rowY int, ch rune) {
|
||||
screen.SetContent(x+colX, y+rowY, ch, nil, borderStyle)
|
||||
}
|
||||
|
||||
// TODO Center in padding amount
|
||||
// TODO incorrect vertical scroll amount
|
||||
|
||||
// Draw the cells (and borders).
|
||||
var columnX int
|
||||
if !t.borders {
|
||||
if !t.cellBorders {
|
||||
columnX--
|
||||
}
|
||||
numRows := len(rows)
|
||||
numCols := len(columns)
|
||||
for columnIndex, column := range columns {
|
||||
columnWidth := widths[columnIndex]
|
||||
for rowY, row := range rows {
|
||||
if t.borders {
|
||||
for i, row := range rows {
|
||||
rowY := i + (t.rowPadding * i * 2)
|
||||
if t.cellBorders {
|
||||
rowY = i*2 + (t.rowPadding * i * 2)
|
||||
// Draw borders.
|
||||
rowY *= 2
|
||||
for pos := 0; pos < columnWidth && columnX+1+pos < width; pos++ {
|
||||
drawBorder(columnX+pos+1, rowY, Borders.Horizontal)
|
||||
}
|
||||
if i == 0 && columnX+columnWidth+1 < width {
|
||||
drawBorder(columnX+columnWidth+1, rowY, Borders.TopRight)
|
||||
}
|
||||
ch := Borders.Cross
|
||||
if columnIndex == 0 {
|
||||
if rowY == 0 {
|
||||
if i == 0 {
|
||||
ch = Borders.TopLeft
|
||||
} else if i == numRows-1 {
|
||||
ch = Borders.BottomLeft
|
||||
} else {
|
||||
ch = Borders.LeftT
|
||||
}
|
||||
} else if rowY == 0 {
|
||||
ch = Borders.TopT
|
||||
} else if i == numRows-1 {
|
||||
if i == 0 {
|
||||
ch = Borders.BottomLeft
|
||||
} else {
|
||||
ch = Borders.BottomT
|
||||
}
|
||||
}
|
||||
drawBorder(columnX, rowY, ch)
|
||||
rowY++
|
||||
if rowY >= height {
|
||||
if rowY+1 >= height {
|
||||
break // No space for the text anymore.
|
||||
}
|
||||
drawBorder(columnX, rowY, Borders.Vertical)
|
||||
rowY += t.rowPadding
|
||||
for j := 0 - t.rowPadding; j < t.rowPadding+1; j++ {
|
||||
if rowY+j >= height {
|
||||
break
|
||||
}
|
||||
drawBorder(columnX, rowY+j, Borders.Vertical)
|
||||
if columnIndex == numCols-1 && columnX+columnWidth+1 < width {
|
||||
drawBorder(columnX+columnWidth+1, rowY+j, Borders.Vertical)
|
||||
}
|
||||
}
|
||||
if columnIndex == numCols-1 && columnX+columnWidth+1 < width && rowY+t.rowPadding+1 <= height {
|
||||
//log.Println(i)
|
||||
if i == numRows-2 {
|
||||
drawBorder(columnX+columnWidth+1, rowY+t.rowPadding+1, Borders.BottomRight)
|
||||
} else {
|
||||
drawBorder(columnX+columnWidth+1, rowY+t.rowPadding+1, Borders.RightT)
|
||||
}
|
||||
}
|
||||
} else if columnIndex > 0 {
|
||||
// Draw separator.
|
||||
drawBorder(columnX, rowY, t.separator)
|
||||
|
@ -1085,39 +1132,9 @@ ColumnLoop:
|
|||
}
|
||||
}
|
||||
|
||||
// Draw bottom border.
|
||||
if rowY := 2 * len(rows); t.borders && rowY < height {
|
||||
for pos := 0; pos < columnWidth && columnX+1+pos < width; pos++ {
|
||||
drawBorder(columnX+pos+1, rowY, Borders.Horizontal)
|
||||
}
|
||||
ch := Borders.BottomT
|
||||
if columnIndex == 0 {
|
||||
ch = Borders.BottomLeft
|
||||
}
|
||||
drawBorder(columnX, rowY, ch)
|
||||
}
|
||||
|
||||
columnX += columnWidth + 1
|
||||
}
|
||||
|
||||
// Draw right border.
|
||||
if t.borders && len(t.cells) > 0 && columnX < width {
|
||||
for rowY := range rows {
|
||||
rowY *= 2
|
||||
if rowY+1 < height {
|
||||
drawBorder(columnX, rowY+1, Borders.Vertical)
|
||||
}
|
||||
ch := Borders.RightT
|
||||
if rowY == 0 {
|
||||
ch = Borders.TopRight
|
||||
}
|
||||
drawBorder(columnX, rowY, ch)
|
||||
}
|
||||
if rowY := 2 * len(rows); rowY < height {
|
||||
drawBorder(columnX, rowY, Borders.BottomRight)
|
||||
}
|
||||
}
|
||||
|
||||
if showVerticalScrollBar {
|
||||
// Calculate scroll bar position and dimensions.
|
||||
rows := len(t.cells)
|
||||
|
@ -1132,7 +1149,7 @@ ColumnLoop:
|
|||
}
|
||||
|
||||
padTotalOffset := 1
|
||||
if t.borders {
|
||||
if t.cellBorders {
|
||||
padTotalOffset = 2
|
||||
|
||||
scrollBarItems *= 2
|
||||
|
@ -1162,7 +1179,7 @@ ColumnLoop:
|
|||
m, c, style, _ := screen.GetContent(fromX+bx, fromY+by)
|
||||
fg, bg, a := style.Decompose()
|
||||
if invert {
|
||||
if fg == textColor || fg == t.bordersColor {
|
||||
if fg == textColor || fg == t.cellBorderColor {
|
||||
fg = backgroundColor
|
||||
}
|
||||
if fg == tcell.ColorDefault {
|
||||
|
@ -1195,7 +1212,8 @@ ColumnLoop:
|
|||
}
|
||||
cellsByBackgroundColor := make(map[tcell.Color][]*cellInfo)
|
||||
var backgroundColors []tcell.Color
|
||||
for rowY, row := range rows {
|
||||
for i, row := range rows {
|
||||
rowY := i + (t.rowPadding * i)
|
||||
columnX := 0
|
||||
rowSelected := t.rowsSelectable && !t.columnsSelectable && row == t.selectedRow
|
||||
for columnIndex, column := range columns {
|
||||
|
@ -1205,8 +1223,8 @@ ColumnLoop:
|
|||
continue
|
||||
}
|
||||
bx, by, bw, bh := x+columnX, y+rowY, columnWidth+1, 1
|
||||
if t.borders {
|
||||
by = y + rowY*2
|
||||
if t.cellBorders {
|
||||
by = y + ((t.columnPadding * i) * 2)
|
||||
bw++
|
||||
bh = 3
|
||||
}
|
||||
|
@ -1430,7 +1448,7 @@ func (t *Table) MouseHandler() func(action MouseAction, event *tcell.EventMouse,
|
|||
_, tableY, _, _ := t.GetInnerRect()
|
||||
mul := 1
|
||||
maxY := tableY
|
||||
if t.borders {
|
||||
if t.cellBorders {
|
||||
mul = 2
|
||||
maxY = tableY + 1
|
||||
}
|
||||
|
@ -1466,3 +1484,19 @@ func (t *Table) MouseHandler() func(action MouseAction, event *tcell.EventMouse,
|
|||
return
|
||||
})
|
||||
}
|
||||
|
||||
// SetBorders sets whether or not each cell in the table is surrounded by a border.
|
||||
//
|
||||
// Deprecated: This function is provided for backwards compatibility.
|
||||
// Developers should use SetCellBorder instead.
|
||||
func (t *Table) SetBorders(show bool) {
|
||||
t.SetCellBorders(show)
|
||||
}
|
||||
|
||||
// SetBordersColor sets the color of the cell borders.
|
||||
//
|
||||
// Deprecated: This function is provided for backwards compatibility.
|
||||
// Developers should use SetCellBorderColor instead.
|
||||
func (t *Table) SetBordersColor(color tcell.Color) {
|
||||
t.SetCellBorderColor(color)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue