mirror of https://github.com/rivo/tview.git
Added mouse support for Table and TreeView.
This commit is contained in:
parent
9af6826328
commit
5f5b79b00e
|
@ -1,6 +1,6 @@
|
|||
# Rich Interactive Widgets for Terminal UIs
|
||||
|
||||
[![Godoc Reference](https://img.shields.io/badge/godoc-reference-blue.svg)](https://godoc.org/github.com/rivo/tview)
|
||||
[![Godoc Reference](https://img.shields.io/badge/godoc-reference-blue.svg)](https://pkg.go.dev/github.com/rivo/tview)
|
||||
[![Go Report](https://img.shields.io/badge/go%20report-A%2B-brightgreen.svg)](https://goreportcard.com/report/github.com/rivo/tview)
|
||||
|
||||
This Go package provides commonly needed components for terminal based user interfaces.
|
||||
|
|
|
@ -39,7 +39,7 @@ func main() {
|
|||
table.GetCell(row, column).SetTextColor(tcell.ColorRed)
|
||||
table.SetSelectable(false, false)
|
||||
})
|
||||
if err := app.SetRoot(table, true).Run(); err != nil {
|
||||
if err := app.SetRoot(table, true).EnableMouse(true).Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
if err := tview.NewApplication().SetRoot(tree, true).Run(); err != nil {
|
||||
if err := tview.NewApplication().SetRoot(tree, true).EnableMouse(true).Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -419,8 +419,7 @@ func (d *DropDown) InputHandler() func(event *tcell.EventKey, setFocus func(p Pr
|
|||
})
|
||||
}
|
||||
|
||||
// evalPrefix is selects an item in the drop-down list based on the current
|
||||
// prefix.
|
||||
// evalPrefix selects an item in the drop-down list based on the current prefix.
|
||||
func (d *DropDown) evalPrefix() {
|
||||
if len(d.prefix) > 0 {
|
||||
for index, option := range d.options {
|
||||
|
@ -430,7 +429,7 @@ func (d *DropDown) evalPrefix() {
|
|||
}
|
||||
}
|
||||
|
||||
// Prefix does not match any item. Remove last rune. TODO: Use uniseg here.
|
||||
// Prefix does not match any item. Remove last rune.
|
||||
r := []rune(d.prefix)
|
||||
d.prefix = string(r[:len(r)-1])
|
||||
}
|
||||
|
|
82
table.go
82
table.go
|
@ -251,6 +251,13 @@ type Table struct {
|
|||
// The number of visible rows the last time the table was drawn.
|
||||
visibleRows int
|
||||
|
||||
// The indices of the visible columns as of the last time the table was drawn.
|
||||
visibleColumnIndices []int
|
||||
|
||||
// The net widths of the visible columns as of the last time the table was
|
||||
// drawn.
|
||||
visibleColumnWidths []int
|
||||
|
||||
// The style of the selected rows. If this value is 0, selected rows are
|
||||
// simply inverted.
|
||||
selectedStyle tcell.Style
|
||||
|
@ -360,8 +367,8 @@ func (t *Table) GetSelection() (row, column int) {
|
|||
// Select sets the selected cell. Depending on the selection settings
|
||||
// specified via SetSelectable(), this may be an entire row or column, or even
|
||||
// ignored completely. The "selection changed" event is fired if such a callback
|
||||
// is available (even if the selection ends up being the same as before, even if
|
||||
// cells are not selectable).
|
||||
// is available (even if the selection ends up being the same as before and even
|
||||
// if cells are not selectable).
|
||||
func (t *Table) Select(row, column int) *Table {
|
||||
t.selectedRow, t.selectedColumn = row, column
|
||||
if t.selectionChanged != nil {
|
||||
|
@ -537,6 +544,49 @@ func (t *Table) GetColumnCount() int {
|
|||
return t.lastColumn + 1
|
||||
}
|
||||
|
||||
// cellAt returns the row and column located at the given screen coordinates.
|
||||
// Each returned value may be negative if there is no row and/or cell. This
|
||||
// function will also process coordinates outside the table's inner rectangle so
|
||||
// callers will need to check for bounds themselves.
|
||||
func (t *Table) cellAt(x, y int) (row, column int) {
|
||||
rectX, rectY, _, _ := t.GetInnerRect()
|
||||
|
||||
// Determine row as seen on screen.
|
||||
if t.borders {
|
||||
row = (y - rectY - 1) / 2
|
||||
} else {
|
||||
row = y - rectY
|
||||
}
|
||||
|
||||
// Respect fixed rows and row offset.
|
||||
if row >= 0 {
|
||||
if row >= t.fixedRows {
|
||||
row += t.rowOffset
|
||||
}
|
||||
if row >= len(t.cells) {
|
||||
row = -1
|
||||
}
|
||||
}
|
||||
|
||||
// Saerch for the clicked column.
|
||||
column = -1
|
||||
if x >= rectX {
|
||||
columnX := rectX
|
||||
if t.borders {
|
||||
columnX++
|
||||
}
|
||||
for index, width := range t.visibleColumnWidths {
|
||||
columnX += width + 1
|
||||
if x < columnX {
|
||||
column = t.visibleColumnIndices[index]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ScrollToBeginning scrolls the table to the beginning to that the top left
|
||||
// corner of the table is shown. Note that this position may be corrected if
|
||||
// there is a selection.
|
||||
|
@ -824,8 +874,8 @@ ColumnLoop:
|
|||
cell.x, cell.y, cell.width = x+columnX+1, y+rowY, finalWidth
|
||||
_, printed := printWithStyle(screen, cell.Text, x+columnX+1, y+rowY, finalWidth, cell.Align, tcell.StyleDefault.Foreground(cell.Color)|tcell.Style(cell.Attributes))
|
||||
if TaggedStringWidth(cell.Text)-printed > 0 && printed > 0 {
|
||||
_, _, style, _ := screen.GetContent(x+columnX+1+finalWidth-1, y+rowY)
|
||||
printWithStyle(screen, string(SemigraphicsHorizontalEllipsis), x+columnX+1+finalWidth-1, y+rowY, 1, AlignLeft, style)
|
||||
_, _, style, _ := screen.GetContent(x+columnX+finalWidth, y+rowY)
|
||||
printWithStyle(screen, string(SemigraphicsHorizontalEllipsis), x+columnX+finalWidth, y+rowY, 1, AlignLeft, style)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -964,6 +1014,9 @@ ColumnLoop:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remember column infos.
|
||||
t.visibleColumnIndices, t.visibleColumnWidths = columns, widths
|
||||
}
|
||||
|
||||
// InputHandler returns the handler for this primitive.
|
||||
|
@ -1173,3 +1226,24 @@ func (t *Table) InputHandler() func(event *tcell.EventKey, setFocus func(p Primi
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
// MouseHandler returns the mouse handler for this primitive.
|
||||
func (t *Table) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
|
||||
return t.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
|
||||
x, y := event.Position()
|
||||
if !t.InRect(x, y) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
switch action {
|
||||
case MouseLeftClick:
|
||||
if t.rowsSelectable || t.columnsSelectable {
|
||||
t.Select(t.cellAt(x, y))
|
||||
}
|
||||
consumed = true
|
||||
setFocus(t)
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
}
|
||||
|
|
32
treeview.go
32
treeview.go
|
@ -730,3 +730,35 @@ func (t *TreeView) InputHandler() func(event *tcell.EventKey, setFocus func(p Pr
|
|||
t.process()
|
||||
})
|
||||
}
|
||||
|
||||
// MouseHandler returns the mouse handler for this primitive.
|
||||
func (t *TreeView) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
|
||||
return t.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) {
|
||||
x, y := event.Position()
|
||||
if !t.InRect(x, y) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
switch action {
|
||||
case MouseLeftClick:
|
||||
_, rectY, _, _ := t.GetInnerRect()
|
||||
y -= rectY
|
||||
if y >= 0 && y < len(t.nodes) {
|
||||
node := t.nodes[y]
|
||||
if node.selectable {
|
||||
if t.currentNode != node && t.changed != nil {
|
||||
t.changed(node)
|
||||
}
|
||||
if t.selected != nil {
|
||||
t.selected(node)
|
||||
}
|
||||
t.currentNode = node
|
||||
}
|
||||
}
|
||||
consumed = true
|
||||
setFocus(t)
|
||||
}
|
||||
|
||||
return
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue