User can now select table cells
This commit is contained in:
parent
ebefcb03b3
commit
b357768c36
@ -2,6 +2,7 @@ package containers
|
|||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo"
|
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/canvas"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
import "git.tebibyte.media/sashakoshka/tomo/artist"
|
||||||
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
import "git.tebibyte.media/sashakoshka/tomo/elements/core"
|
||||||
@ -10,7 +11,7 @@ import "git.tebibyte.media/sashakoshka/tomo/default/config"
|
|||||||
|
|
||||||
type tableCell struct {
|
type tableCell struct {
|
||||||
tomo.Element
|
tomo.Element
|
||||||
artist.Pattern
|
tomo.Pattern
|
||||||
image.Rectangle
|
image.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,9 +36,13 @@ type TableContainer struct {
|
|||||||
forcedMinimumWidth int
|
forcedMinimumWidth int
|
||||||
forcedMinimumHeight int
|
forcedMinimumHeight int
|
||||||
|
|
||||||
|
selectedColumn int
|
||||||
|
selectedRow int
|
||||||
|
|
||||||
config config.Wrapped
|
config config.Wrapped
|
||||||
theme theme.Wrapped
|
theme theme.Wrapped
|
||||||
|
|
||||||
|
onSelect func ()
|
||||||
onScrollBoundsChange func ()
|
onScrollBoundsChange func ()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +55,8 @@ func NewTableContainer (
|
|||||||
element = &TableContainer {
|
element = &TableContainer {
|
||||||
topHeading: topHeading,
|
topHeading: topHeading,
|
||||||
leftHeading: leftHeading,
|
leftHeading: leftHeading,
|
||||||
|
selectedColumn: -1,
|
||||||
|
selectedRow: -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
element.theme.Case = tomo.C("tomo", "tableContainer")
|
element.theme.Case = tomo.C("tomo", "tableContainer")
|
||||||
@ -153,6 +160,17 @@ func (element *TableContainer) Resize (columns, rows int) {
|
|||||||
element.redoAll()
|
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
|
// Warp runs the specified callback, deferring all layout and rendering updates
|
||||||
// until the callback has finished executing. This allows for aplications to
|
// until the callback has finished executing. This allows for aplications to
|
||||||
// perform batch gui updates without flickering and stuff.
|
// 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) {
|
func (element *TableContainer) DrawBackground (bounds image.Rectangle) {
|
||||||
if !bounds.Overlaps(element.core.Bounds()) { return }
|
if !bounds.Overlaps(element.core.Bounds()) { return }
|
||||||
|
|
||||||
for _, row := range element.grid {
|
for rowIndex, row := range element.grid {
|
||||||
for _, child := range row {
|
for columnIndex, child := range row {
|
||||||
if bounds.Overlaps(child.Rectangle) {
|
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
|
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) {
|
func (element *TableContainer) hook (child tomo.Element) {
|
||||||
if child0, ok := child.(tomo.Themeable); ok {
|
if child0, ok := child.(tomo.Themeable); ok {
|
||||||
child0.SetTheme(element.theme.Theme)
|
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 () {
|
func (element *TableContainer) redoAll () {
|
||||||
if element.warping || !element.core.HasImage() {
|
if element.warping || !element.core.HasImage() {
|
||||||
element.updateMinimumSize()
|
element.updateMinimumSize()
|
||||||
@ -294,7 +370,7 @@ func (element *TableContainer) redoAll () {
|
|||||||
x := float64(bounds.Min.X)
|
x := float64(bounds.Min.X)
|
||||||
y := float64(bounds.Min.Y)
|
y := float64(bounds.Min.Y)
|
||||||
for rowIndex, row := range element.grid {
|
for rowIndex, row := range element.grid {
|
||||||
for columnIndex, child := range row {
|
for columnIndex, _ := range row {
|
||||||
width := columnWidths[columnIndex]
|
width := columnWidths[columnIndex]
|
||||||
height := rowHeights[rowIndex]
|
height := rowHeights[rowIndex]
|
||||||
cellBounds := image.Rect (
|
cellBounds := image.Rect (
|
||||||
@ -310,26 +386,10 @@ func (element *TableContainer) redoAll () {
|
|||||||
} else {
|
} else {
|
||||||
id = tomo.PatternTableCell
|
id = tomo.PatternTableCell
|
||||||
}
|
}
|
||||||
pattern := element.theme.Pattern(id, tomo.State { })
|
|
||||||
element.grid[rowIndex][columnIndex].Rectangle = cellBounds
|
element.grid[rowIndex][columnIndex].Rectangle = cellBounds
|
||||||
element.grid[rowIndex][columnIndex].Pattern = pattern
|
element.grid[rowIndex][columnIndex].Pattern = id
|
||||||
|
|
||||||
if child.Element != nil {
|
element.redoCell(columnIndex, rowIndex)
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
x += float64(width)
|
x += float64(width)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,3 +431,7 @@ func (element *TableContainer) updateMinimumSize () {
|
|||||||
|
|
||||||
element.core.SetMinimumSize(minWidth, minHeight)
|
element.core.SetMinimumSize(minWidth, minHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (element *TableContainer) childDrawCallback (region image.Rectangle) {
|
||||||
|
element.core.DamageRegion(region)
|
||||||
|
}
|
||||||
|
@ -29,10 +29,18 @@ func run () {
|
|||||||
}
|
}
|
||||||
index ++
|
index ++
|
||||||
}}
|
}}
|
||||||
|
|
||||||
table.Set(2, 1, elements.NewButton("Look, I'm a button!"))
|
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(table, true)
|
||||||
|
container.Adopt(statusLabel, false)
|
||||||
window.Adopt(container)
|
window.Adopt(container)
|
||||||
|
|
||||||
window.OnClose(tomo.Stop)
|
window.OnClose(tomo.Stop)
|
||||||
|
Reference in New Issue
Block a user