User can now select table cells
This commit is contained in:
parent
ebefcb03b3
commit
b357768c36
@ -2,6 +2,7 @@ package containers
|
||||
|
||||
import "image"
|
||||
import "git.tebibyte.media/sashakoshka/tomo"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/input"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/canvas"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||
@ -10,7 +11,7 @@ import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
||||
|
||||
type tableCell struct {
|
||||
tomo.Element
|
||||
artist.Pattern
|
||||
tomo.Pattern
|
||||
image.Rectangle
|
||||
}
|
||||
|
||||
@ -35,9 +36,13 @@ type TableContainer struct {
|
||||
forcedMinimumWidth int
|
||||
forcedMinimumHeight int
|
||||
|
||||
selectedColumn int
|
||||
selectedRow int
|
||||
|
||||
config config.Wrapped
|
||||
theme theme.Wrapped
|
||||
|
||||
onSelect func ()
|
||||
onScrollBoundsChange func ()
|
||||
}
|
||||
|
||||
@ -50,6 +55,8 @@ func NewTableContainer (
|
||||
element = &TableContainer {
|
||||
topHeading: topHeading,
|
||||
leftHeading: leftHeading,
|
||||
selectedColumn: -1,
|
||||
selectedRow: -1,
|
||||
}
|
||||
|
||||
element.theme.Case = tomo.C("tomo", "tableContainer")
|
||||
@ -153,6 +160,17 @@ func (element *TableContainer) Resize (columns, rows int) {
|
||||
element.redoAll()
|
||||
}
|
||||
|
||||
// Selected returns the column and row of the cell that is currently selected.
|
||||
// If no cell is selected, this method will return (-1, -1).
|
||||
func (element *TableContainer) Selected () (column, row int) {
|
||||
return element.selectedColumn, element.selectedRow
|
||||
}
|
||||
|
||||
// OnSelect sets a function to be called when the user selects a table cell.
|
||||
func (element *TableContainer) OnSelect (callback func ()) {
|
||||
element.onSelect = callback
|
||||
}
|
||||
|
||||
// Warp runs the specified callback, deferring all layout and rendering updates
|
||||
// until the callback has finished executing. This allows for aplications to
|
||||
// perform batch gui updates without flickering and stuff.
|
||||
@ -212,14 +230,42 @@ func (element *TableContainer) NotifyMinimumSizeChange (child tomo.Element) {
|
||||
func (element *TableContainer) DrawBackground (bounds image.Rectangle) {
|
||||
if !bounds.Overlaps(element.core.Bounds()) { return }
|
||||
|
||||
for _, row := range element.grid {
|
||||
for _, child := range row {
|
||||
for rowIndex, row := range element.grid {
|
||||
for columnIndex, child := range row {
|
||||
if bounds.Overlaps(child.Rectangle) {
|
||||
child.Draw(canvas.Cut(element.core, bounds), child.Rectangle)
|
||||
element.theme.Pattern (
|
||||
child.Pattern,
|
||||
element.state(columnIndex, rowIndex)).
|
||||
Draw(canvas.Cut(element.core, bounds), child.Rectangle)
|
||||
return
|
||||
}}}
|
||||
}
|
||||
|
||||
func (element *TableContainer) HandleMouseDown (x, y int, button input.Button) {
|
||||
element.Propagator.HandleMouseDown(x, y, button)
|
||||
if button != input.ButtonLeft { return }
|
||||
|
||||
for rowIndex, row := range element.grid {
|
||||
for columnIndex, child := range row {
|
||||
if image.Pt(x, y).In(child.Rectangle) {
|
||||
selected :=
|
||||
rowIndex == element.selectedRow &&
|
||||
columnIndex == element.selectedColumn
|
||||
if selected { return }
|
||||
oldColumn, oldRow := element.selectedColumn, element.selectedRow
|
||||
element.selectedColumn, element.selectedRow = columnIndex, rowIndex
|
||||
if oldColumn >= 0 && oldRow >= 0 {
|
||||
element.core.DamageRegion(element.redoCell(oldColumn, oldRow))
|
||||
}
|
||||
element.core.DamageRegion(element.redoCell(columnIndex, rowIndex))
|
||||
if element.onSelect != nil {
|
||||
element.onSelect()
|
||||
}
|
||||
return
|
||||
}}}
|
||||
|
||||
}
|
||||
|
||||
func (element *TableContainer) hook (child tomo.Element) {
|
||||
if child0, ok := child.(tomo.Themeable); ok {
|
||||
child0.SetTheme(element.theme.Theme)
|
||||
@ -245,6 +291,36 @@ func (element *TableContainer) rebuildChildList (list []tomo.Element) {
|
||||
}}
|
||||
}
|
||||
|
||||
func (element *TableContainer) state (column, row int) (state tomo.State) {
|
||||
if column == element.selectedColumn && row == element.selectedRow {
|
||||
state.On = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (element *TableContainer) redoCell (column, row int) image.Rectangle {
|
||||
padding := element.theme.Padding(tomo.PatternTableCell)
|
||||
cell := element.grid[row][column]
|
||||
pattern := element.theme.Pattern (
|
||||
cell.Pattern, element.state(column, row))
|
||||
|
||||
if cell.Element != nil {
|
||||
// give child canvas portion
|
||||
innerCellBounds := padding.Apply(cell.Rectangle)
|
||||
artist.DrawShatter (
|
||||
element.core, pattern,
|
||||
cell.Rectangle, innerCellBounds)
|
||||
cell.DrawTo (
|
||||
canvas.Cut(element.core, innerCellBounds),
|
||||
innerCellBounds,
|
||||
element.childDrawCallback)
|
||||
} else {
|
||||
// draw cell pattern in empty cells
|
||||
pattern.Draw(element.core, cell.Rectangle)
|
||||
}
|
||||
return cell.Rectangle
|
||||
}
|
||||
|
||||
func (element *TableContainer) redoAll () {
|
||||
if element.warping || !element.core.HasImage() {
|
||||
element.updateMinimumSize()
|
||||
@ -294,7 +370,7 @@ func (element *TableContainer) redoAll () {
|
||||
x := float64(bounds.Min.X)
|
||||
y := float64(bounds.Min.Y)
|
||||
for rowIndex, row := range element.grid {
|
||||
for columnIndex, child := range row {
|
||||
for columnIndex, _ := range row {
|
||||
width := columnWidths[columnIndex]
|
||||
height := rowHeights[rowIndex]
|
||||
cellBounds := image.Rect (
|
||||
@ -310,26 +386,10 @@ func (element *TableContainer) redoAll () {
|
||||
} else {
|
||||
id = tomo.PatternTableCell
|
||||
}
|
||||
pattern := element.theme.Pattern(id, tomo.State { })
|
||||
element.grid[rowIndex][columnIndex].Rectangle = cellBounds
|
||||
element.grid[rowIndex][columnIndex].Pattern = pattern
|
||||
element.grid[rowIndex][columnIndex].Pattern = id
|
||||
|
||||
if child.Element != nil {
|
||||
// give child canvas portion
|
||||
innerCellBounds := padding.Apply(cellBounds)
|
||||
artist.DrawShatter (
|
||||
element.core, pattern,
|
||||
cellBounds, innerCellBounds)
|
||||
child.DrawTo (
|
||||
canvas.Cut(element.core, innerCellBounds),
|
||||
innerCellBounds,
|
||||
func (region image.Rectangle) {
|
||||
element.core.DamageRegion(region)
|
||||
})
|
||||
} else {
|
||||
// draw cell pattern in empty cells
|
||||
pattern.Draw(element.core, cellBounds)
|
||||
}
|
||||
element.redoCell(columnIndex, rowIndex)
|
||||
x += float64(width)
|
||||
}
|
||||
|
||||
@ -371,3 +431,7 @@ func (element *TableContainer) updateMinimumSize () {
|
||||
|
||||
element.core.SetMinimumSize(minWidth, minHeight)
|
||||
}
|
||||
|
||||
func (element *TableContainer) childDrawCallback (region image.Rectangle) {
|
||||
element.core.DamageRegion(region)
|
||||
}
|
||||
|
@ -29,10 +29,18 @@ func run () {
|
||||
}
|
||||
index ++
|
||||
}}
|
||||
|
||||
table.Set(2, 1, elements.NewButton("Look, I'm a button!"))
|
||||
|
||||
statusLabel := elements.NewLabel("Selected: none", false)
|
||||
table.OnSelect (func () {
|
||||
column, row := table.Selected()
|
||||
statusLabel.SetText (
|
||||
fmt.Sprintf("Selected: %d, %d",
|
||||
column, row))
|
||||
})
|
||||
|
||||
container.Adopt(table, true)
|
||||
container.Adopt(statusLabel, false)
|
||||
window.Adopt(container)
|
||||
|
||||
window.OnClose(tomo.Stop)
|
||||
|
Reference in New Issue
Block a user