183 lines
3.3 KiB
Go
183 lines
3.3 KiB
Go
package termui
|
|
|
|
import (
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// Table tracks all the attributes of a Table instance
|
|
type Table struct {
|
|
*Block
|
|
Header []string
|
|
Rows [][]string
|
|
Fg Attribute
|
|
Bg Attribute
|
|
Cursor Attribute
|
|
UniqueCol int
|
|
pid string
|
|
selected int
|
|
topRow int
|
|
}
|
|
|
|
// NewTable returns a new Table instance
|
|
func NewTable() *Table {
|
|
return &Table{
|
|
Block: NewBlock(),
|
|
Fg: Theme.Fg,
|
|
Bg: Theme.Bg,
|
|
Cursor: Theme.TableCursor,
|
|
selected: 0,
|
|
topRow: 0,
|
|
UniqueCol: 0,
|
|
}
|
|
}
|
|
|
|
// Buffer ...
|
|
func (t *Table) Buffer() *Buffer {
|
|
buf := t.Block.Buffer()
|
|
|
|
if t.topRow > len(t.Rows)-(t.Y-1) {
|
|
t.topRow = len(t.Rows) - (t.Y - 1)
|
|
}
|
|
|
|
// calculate gap size based on total width
|
|
gap := 3
|
|
if t.X < 50 {
|
|
gap = 1
|
|
} else if t.X < 75 {
|
|
gap = 2
|
|
}
|
|
|
|
cw := []int{5, 10, 4, 4} // cellWidth
|
|
cp := []int{ // cellPosition
|
|
gap,
|
|
gap + cw[0] + gap,
|
|
t.X - gap - cw[3] - gap - cw[2],
|
|
t.X - gap - cw[3],
|
|
}
|
|
|
|
// total width requires by all 4 columns
|
|
contentWidth := gap + cw[0] + gap + cw[1] + gap + cw[2] + gap + cw[3] + gap
|
|
render := 4 // number of columns to iterate through
|
|
|
|
// removes CPU and MEM if there isn't enough room
|
|
if t.X < (contentWidth - gap - cw[3]) {
|
|
render = 2
|
|
} else if t.X < contentWidth {
|
|
cp[2] = cp[3]
|
|
render = 3
|
|
}
|
|
|
|
// print header
|
|
for i := 0; i < render; i++ {
|
|
r := MaxString(t.Header[i], t.X-6)
|
|
buf.SetString(cp[i], 1, r, t.Fg|AttrBold, t.Bg)
|
|
}
|
|
|
|
// prints each row
|
|
// for y, row := range t.Rows {
|
|
// for y := t.topRow; y <= t.topRow+t.Y; y++ {
|
|
for rowNum := t.topRow; rowNum < t.topRow+t.Y-1 && rowNum < len(t.Rows); rowNum++ {
|
|
row := t.Rows[rowNum]
|
|
y := (rowNum + 2) - t.topRow
|
|
|
|
// cursor
|
|
bg := t.Bg
|
|
if (t.pid == "" && rowNum == t.selected) || (t.pid != "" && t.pid == row[t.UniqueCol]) {
|
|
bg = t.Cursor
|
|
for i := 0; i < render; i++ {
|
|
buf.SetString(1, y, strings.Repeat(" ", t.X), t.Fg, bg)
|
|
}
|
|
t.pid = row[t.UniqueCol]
|
|
t.selected = rowNum
|
|
}
|
|
|
|
// prints each string
|
|
for i := 0; i < render; i++ {
|
|
r := MaxString(row[i], t.X-6)
|
|
buf.SetString(cp[i], y, r, t.Fg, bg)
|
|
}
|
|
}
|
|
|
|
return buf
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
func (t *Table) calcPos() {
|
|
t.pid = ""
|
|
|
|
if t.selected < 0 {
|
|
t.selected = 0
|
|
}
|
|
if t.selected < t.topRow {
|
|
t.topRow = t.selected
|
|
}
|
|
|
|
if t.selected > len(t.Rows)-1 {
|
|
t.selected = len(t.Rows) - 1
|
|
}
|
|
if t.selected > t.topRow+(t.Y-2) {
|
|
t.topRow = t.selected - (t.Y - 2)
|
|
}
|
|
}
|
|
|
|
func (t *Table) Up() {
|
|
t.selected -= 1
|
|
t.calcPos()
|
|
}
|
|
|
|
func (t *Table) Down() {
|
|
t.selected += 1
|
|
t.calcPos()
|
|
}
|
|
|
|
func (t *Table) Top() {
|
|
t.selected = 0
|
|
t.calcPos()
|
|
}
|
|
|
|
func (t *Table) Bottom() {
|
|
t.selected = len(t.Rows) - 1
|
|
t.calcPos()
|
|
}
|
|
|
|
func (t *Table) HalfPageUp() {
|
|
t.selected = t.selected - (t.Y-2)/2
|
|
t.calcPos()
|
|
}
|
|
|
|
func (t *Table) HalfPageDown() {
|
|
t.selected = t.selected + (t.Y-2)/2
|
|
t.calcPos()
|
|
}
|
|
|
|
func (t *Table) PageUp() {
|
|
t.selected -= (t.Y - 2)
|
|
t.calcPos()
|
|
}
|
|
|
|
func (t *Table) PageDown() {
|
|
t.selected += (t.Y - 2)
|
|
t.calcPos()
|
|
}
|
|
|
|
func (t *Table) Click(x, y int) {
|
|
x = x - t.XOffset
|
|
y = y - t.YOffset
|
|
if (x > 0 && x <= t.X) && (y > 0 && y <= t.Y) {
|
|
t.selected = (t.topRow + y) - 2
|
|
t.calcPos()
|
|
}
|
|
}
|
|
|
|
func (t *Table) Kill() {
|
|
t.pid = ""
|
|
command := "kill"
|
|
if t.UniqueCol == 1 {
|
|
command = "pkill"
|
|
}
|
|
cmd := exec.Command(command, t.Rows[t.selected][t.UniqueCol])
|
|
cmd.Start()
|
|
}
|